diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index fe16e58..0cd01d1 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,7 +8,7 @@ Please also include the context and motivation about the changes introduced. - Documentation ## Checks -- [ ] Changes support all platforms (`Android`, `iOS`, `Linux`, macOS`, `tvOS`) +- [ ] Changes support all platforms (`Android`, `iOS`, `Linux`, `macOS`, `tvOS`) - [ ] Breaks existing functionality - [ ] Implementation is completed, not half-done - [ ] Is there another PR already created for this feature/bug fix diff --git a/README.md b/README.md index 9066843..b9644ae 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ It includes scripts to build `FFmpeg` native libraries, a wrapper library to run - Supports hybrid platforms: Flutter, React Native - Based on FFmpeg `v4.5-dev` or later with optional system and external libraries - 8 prebuilt binary packages available at [Github](https://github.com/arthenica/ffmpeg-kit/releases), [Maven Central](https://search.maven.org), [CocoaPods](https://cocoapods.org), [pub](https://pub.dev) and [npm](https://www.npmjs.com) -- Licensed under `LGPL 3.0`, or `GPL v3.0` if GPL licensed libraries are enabled +- Licensed under `LGPL 3.0` by default, `GPL v3.0` if GPL licensed libraries are enabled ### 2. Android @@ -124,23 +124,23 @@ the same `FFmpeg` release branch. `dev` part in the version string indicates that `FFmpeg` source code is cloned from the `FFmpeg` `master` branch and the exact version number of `FFmpeg` is obtained using the `git describe --tags` command. -| Platforms | FFmpegKit Version | FFmpeg Version | Release Date | -|:----------------:|:----------------------------------------------------------------------------------:|:--------------:|:------------:| -| Android | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | -| Apple | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | -| React Native | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v5.1.0) | 5.1.2 | Oct 03, 2022 | -| Flutter | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v5.1.0) | 5.1.2 | Oct 02, 2022 | -| Android | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | -| Apple | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | -| React Native | [4.5.2](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.2) | 4.5-dev-3393 | May 25, 2022 | -| Flutter | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v4.5.1) | 4.5-dev-3393 | Jan 02, 2022 | -| React Native | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.1) | 4.5-dev-3393 | Jan 02, 2022 | -| Android | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5.1) | 4.5-dev-3393 | Jan 01, 2022 | -| Apple | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5.1) | 4.5-dev-3393 | Dec 30, 2021 | -| Flutter | [4.5.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v4.5.0) | 4.5-dev-2008 | Oct 05, 2021 | -| React Native | [4.5.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.0) | 4.5-dev-2008 | Oct 01, 2021 | -| Android
Apple | [4.5](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5) | 4.5-dev-2008 | Sep 18, 2021 | -| Android
Apple | [4.4](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.4) | 4.4-dev-3015 | Mar 03, 2021 | +| Platforms | FFmpegKit Version | FFmpeg Version | Release Date | +|:----------------:|:-----------------------------------------------------------------------------------:|:--------------:|:------------:| +| Android | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | +| Apple | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | +| React Native | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v5.1.0) | 5.1.2 | Oct 02, 2022 | +| Flutter | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v5.1.0) | 5.1.2 | Oct 02, 2022 | +| Android | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | +| Apple | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | +| React Native | [4.5.2](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.2) | 4.5-dev-3393 | May 25, 2022 | +| Flutter | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v4.5.1) | 4.5-dev-3393 | Jan 02, 2022 | +| React Native | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.1) | 4.5-dev-3393 | Jan 02, 2022 | +| Android | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5.1) | 4.5-dev-3393 | Jan 01, 2022 | +| Apple | [4.5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5.1) | 4.5-dev-3393 | Dec 30, 2021 | +| Flutter | [4.5.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v4.5.0) | 4.5-dev-2008 | Oct 05, 2021 | +| React Native | [4.5.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v4.5.0) | 4.5-dev-2008 | Oct 01, 2021 | +| Android
Apple | [4.5](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.5) | 4.5-dev-2008 | Sep 18, 2021 | +| Android
Apple | [4.4](https://github.com/arthenica/ffmpeg-kit/releases/tag/v4.4) | 4.4-dev-3015 | Mar 03, 2021 | ### 11. LTS Releases diff --git a/docs/index.md b/docs/index.md index 573c203..a752fba 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,7 +15,7 @@ applications and 8 prebuilt binary packages available at [Github](https://github - Supports hybrid platforms: Flutter, React Native - Based on FFmpeg `v4.5-dev` or later with optional system and external libraries - 8 prebuilt binary packages available at [Github](https://github.com/arthenica/ffmpeg-kit/releases), [Maven Central](https://search.maven.org), [CocoaPods](https://cocoapods.org), [pub](https://pub.dev) and [npm](https://www.npmjs.com) -- Licensed under `LGPL 3.0`, or `GPL v3.0` if GPL licensed libraries are enabled +- Licensed under `LGPL 3.0` by default, some packages licensed by `GPL v3.0` effectively ### 2. Android @@ -116,7 +116,7 @@ the exact version number of `FFmpeg` is obtained using the `git describe --tags` |:----------------:|:---------------------------------------------------------------------------------:|:--------------:|:------------:| | Android | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | | Apple | [6.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/v6.0) | 6.0 | Aug 21, 2023 | -| React Native | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v5.1.0) | 5.1.2 | Oct 03, 2022 | +| React Native | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/react.native.v5.1.0) | 5.1.2 | Oct 02, 2022 | | Flutter | [5.1.0](https://github.com/arthenica/ffmpeg-kit/releases/tag/flutter.v5.1.0) | 5.1.2 | Oct 02, 2022 | | Android | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | | Apple | [5.1](https://github.com/arthenica/ffmpeg-kit/releases/tag/v5.1) | 5.1.2 | Sep 29, 2022 | diff --git a/flutter/flutter/CHANGELOG.md b/flutter/flutter/CHANGELOG.md index 31f1289..38e6d3f 100644 --- a/flutter/flutter/CHANGELOG.md +++ b/flutter/flutter/CHANGELOG.md @@ -1,3 +1,13 @@ +## 5.1.0 +- Feature release based on native v5.1 +- Implements AbstractSession.cancel() method +- Runs iOS and macOS callbacks on main queue + +## 5.1.0-LTS +- Feature release based on native v5.1.LTS +- Implements AbstractSession.cancel() method +- Runs iOS and macOS callbacks on main queue + ## 4.5.1 - Feature release based on native v4.5.1 diff --git a/flutter/flutter/README.md b/flutter/flutter/README.md index 8e2f409..b5623bd 100644 --- a/flutter/flutter/README.md +++ b/flutter/flutter/README.md @@ -5,14 +5,17 @@ - Includes both `FFmpeg` and `FFprobe` - Supports - `Android`, `iOS` and `macOS` - - FFmpeg `v4.5-dev` releases + - FFmpeg `v5.1.2` - `arm-v7a`, `arm-v7a-neon`, `arm64-v8a`, `x86` and `x86_64` architectures on Android - - `Android API Level 16` or later + - `Android API Level 24` or later + - `API Level 16` on LTS releases - `armv7`, `armv7s`, `arm64`, `arm64-simulator`, `i386`, `x86_64`, `x86_64-mac-catalyst` and `arm64-mac-catalyst` architectures on iOS - - `iOS SDK 10` or later + - `iOS SDK 12.1` or later + - `iOS SDK 10` on LTS releases - `arm64` and `x86_64` architectures on macOS - - `macOS SDK 10.12+` or later + - `macOS SDK 10.15` or later + - `macOS SDK 10.12` on LTS releases - Can process Storage Access Framework (SAF) Uris on Android - 25 external libraries @@ -24,7 +27,7 @@ `vid.stab`, `x264`, `x265`, `xvidcore` -- Licensed under LGPL 3.0, can be customized to support GPL v3.0 +- Licensed under `LGPL 3.0` by default, some packages licensed by `GPL v3.0` effectively ### 2. Installation @@ -32,21 +35,21 @@ Add `ffmpeg_kit_flutter` as a dependency in your `pubspec.yaml file`. ```yaml dependencies: - ffmpeg_kit_flutter: 4.5.1 + ffmpeg_kit_flutter: 5.1.0 ``` #### 2.1 Packages -`ffmpeg` includes built-in encoders for some popular formats. However, there are certain external libraries that needs +`FFmpeg` includes built-in encoders for some popular formats. However, there are certain external libraries that needs to be enabled in order to encode specific formats/codecs. For example, to encode an `mp3` file you need `lame` or `shine` library enabled. You have to install a `ffmpeg_kit_flutter` package that has at least one of them inside. To encode an `h264` video, you need to install a package with `x264` inside. To encode `vp8` or `vp9` videos, you need a `ffmpeg_kit_flutter` package with `libvpx` inside. `ffmpeg-kit` provides eight packages that include different sets of external libraries. These packages are named -according to the external libraries included in them. Refer to -[Packages](https://github.com/arthenica/ffmpeg-kit#8-packages) section of the project README to see the names of those -packages and external libraries included in each of them. +according to the external libraries included. Refer to the +[Packages](https://github.com/arthenica/ffmpeg-kit/wiki/Packages) wiki page to see the names of those +packages and external libraries included in each one of them. #### 2.2 Installing Packages @@ -55,7 +58,7 @@ using the following dependency format. ```yaml dependencies: - ffmpeg_kit_flutter_: 4.5.1 + ffmpeg_kit_flutter_: 5.1.0 ``` Note that hyphens in the package name must be replaced with underscores. Additionally, do not forget to use the package @@ -67,39 +70,44 @@ In order to install the `LTS` variant, append `-LTS` to the version you have for ```yaml dependencies: - ffmpeg_kit_flutter: 4.5.1-LTS + ffmpeg_kit_flutter: 5.1.0-LTS ``` #### 2.4 LTS Releases -`ffmpeg_kit_flutter` is published in two different variants: `Main Release` and `LTS Release`. Both releases share the -same source code but is built with different settings (Architectures, API Level, iOS Min SDK, etc.). Refer to -[LTS Releases](https://github.com/arthenica/ffmpeg-kit#10-lts-releases) section of the project README to see how they -compare to each other. +`ffmpeg_kit_flutter` is published in two variants: `Main Release` and `LTS Release`. Both releases share the +same source code but is built with different settings (Architectures, API Level, iOS Min SDK, etc.). Refer to the +[LTS Releases](https://github.com/arthenica/ffmpeg-kit/wiki/LTS-Releases) wiki page to see how they differ from each +other. -#### 2.5 Android and iOS Support +#### 2.5 Platform Support -The following table shows the Android API level and iOS deployment target required in `ffmpeg_kit_flutter` releases. +The following table shows Android API level, iOS deployment target and macOS deployment target requirements in +`ffmpeg_kit_flutter` releases. - - + + + + + +
Main ReleaseLTS ReleaseMain ReleaseLTS Release
Android
API Level
iOS Minimum
Deployment Target
macOS Minimum
Deployment Target
Android
API Level
iOS Minimum
Deployment Target
macOS Minimum
Deployment Target
24 12.110.15 16 1010.12
diff --git a/flutter/flutter/android/build.gradle b/flutter/flutter/android/build.gradle index 0a033dc..7c6b559 100644 --- a/flutter/flutter/android/build.gradle +++ b/flutter/flutter/android/build.gradle @@ -1,24 +1,31 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:7.1.2' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() } } apply plugin: 'com.android.library' android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { minSdkVersion 24 - targetSdkVersion 30 - versionCode 451 - versionName "4.5.1" + targetSdkVersion 31 + versionCode 510 + versionName "5.1.0" } buildTypes { @@ -35,14 +42,7 @@ android { } } -repositories { - mavenCentral() - jcenter() - google() -} - dependencies { implementation 'androidx.annotation:annotation:1.2.0' - implementation 'com.arthenica:ffmpeg-kit-https:4.5.1-1' + implementation 'com.arthenica:ffmpeg-kit-https:5.1' } - diff --git a/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java b/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java index 3d227bb..479ce82 100644 --- a/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java +++ b/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -831,7 +831,7 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met // FFmpegSession protected void ffmpegSession(@NonNull final List arguments, @NonNull final Result result) { - final FFmpegSession session = new FFmpegSession(arguments.toArray(new String[0]), null, null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS); + final FFmpegSession session = FFmpegSession.create(arguments.toArray(new String[0]), null, null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS); resultHandler.successAsync(result, toMap(session)); } @@ -872,14 +872,14 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met // FFprobeSession protected void ffprobeSession(@NonNull final List arguments, @NonNull final Result result) { - final FFprobeSession session = new FFprobeSession(arguments.toArray(new String[0]), null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS); + final FFprobeSession session = FFprobeSession.create(arguments.toArray(new String[0]), null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS); resultHandler.successAsync(result, toMap(session)); } // MediaInformationSession protected void mediaInformationSession(@NonNull final List arguments, @NonNull final Result result) { - final MediaInformationSession session = new MediaInformationSession(arguments.toArray(new String[0]), null, null); + final MediaInformationSession session = MediaInformationSession.create(arguments.toArray(new String[0]), null, null); resultHandler.successAsync(result, toMap(session)); } diff --git a/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m b/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m index c7b5f8a..a2dac73 100644 --- a/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m +++ b/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -112,30 +112,40 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; - (void)registerGlobalCallbacks { [FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableLogCallback: ^(Log* log){ if (self->logsEnabled) { NSDictionary *dictionary = [FFmpegKitFlutterPlugin toLogDictionary:log]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_LOG_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_LOG_CALLBACK_EVENT withDictionary:dictionary]); + }); } }]; [FFmpegKitConfig enableStatisticsCallback:^(Statistics* statistics){ if (self->statisticsEnabled) { NSDictionary *dictionary = [FFmpegKitFlutterPlugin toStatisticsDictionary:statistics]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_STATISTICS_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_STATISTICS_CALLBACK_EVENT withDictionary:dictionary]); + }); } }]; } @@ -563,7 +573,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFmpegSession - (void)ffmpegSession:(NSArray*)arguments result:(FlutterResult)result { - FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFmpegSession* session = [FFmpegSession create:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } @@ -604,14 +614,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFprobeSession - (void)ffprobeSession:(NSArray*)arguments result:(FlutterResult)result { - FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFprobeSession* session = [FFprobeSession create:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } // MediaInformationSession - (void)mediaInformationSession:(NSArray*)arguments result:(FlutterResult)result { - MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil]; + MediaInformationSession* session = [MediaInformationSession create:arguments withCompleteCallback:nil withLogCallback:nil]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } @@ -632,23 +642,21 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // MediaInformationJsonParser - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; result([FFmpegKitFlutterPlugin toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"Parsing MediaInformation failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); result(nil); } } - (void)mediaInformationJsonParserFromWithError:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; result([FFmpegKitFlutterPlugin toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"Parsing MediaInformation failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); result([FlutterError errorWithCode:@"PARSE_FAILED" message:@"Parsing MediaInformation failed with JSON error." details:nil]); } } diff --git a/flutter/flutter/ios/ffmpeg_kit_flutter.podspec b/flutter/flutter/ios/ffmpeg_kit_flutter.podspec index ba33a6e..afd9360 100644 --- a/flutter/flutter/ios/ffmpeg_kit_flutter.podspec +++ b/flutter/flutter/ios/ffmpeg_kit_flutter.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ffmpeg_kit_flutter' - s.version = '4.5.1' + s.version = '5.1.0' s.summary = 'FFmpeg Kit for Flutter' s.description = 'A Flutter plugin for running FFmpeg and FFprobe commands.' s.homepage = 'https://github.com/arthenica/ffmpeg-kit' @@ -23,112 +23,112 @@ Pod::Spec.new do |s| s.subspec 'min' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-min', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-min', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'min-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-min', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-min', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'min-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-min-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-min-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'min-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-min-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-min-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'https' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-https', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-https', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'https-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-https', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-https', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'https-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-https-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-https-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'https-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-https-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-https-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'audio' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-audio', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-audio', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'audio-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-audio', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-audio', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'video' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-video', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-video', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'video-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-video', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-video', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'full' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-full', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-full', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'full-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-full', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-full', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'full-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-full-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-full-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'full-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-ios-full-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-full-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end diff --git a/flutter/flutter/lib/abstract_session.dart b/flutter/flutter/lib/abstract_session.dart index 4667569..4cbb521 100644 --- a/flutter/flutter/lib/abstract_session.dart +++ b/flutter/flutter/lib/abstract_session.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -35,7 +35,7 @@ import 'src/ffmpeg_kit_factory.dart'; /// Abstract session implementation which includes common features shared by /// "FFmpeg", "FFprobe" and "MediaInformation" sessions. -class AbstractSession extends Session { +abstract class AbstractSession extends Session { static FFmpegKitPlatform _platform = FFmpegKitPlatform.instance; /// Defines how long default "getAll" methods wait, in milliseconds. @@ -428,5 +428,18 @@ class AbstractSession extends Session { bool isMediaInformation() => false; /// Cancels running the session. - void cancel() {} + Future cancel() async { + try { + final int? sessionId = getSessionId(); + await FFmpegKitConfig.init(); + if (sessionId == null) { + return _platform.ffmpegKitCancel(); + } else { + return _platform.ffmpegKitCancelSession(sessionId); + } + } on PlatformException catch (e, stack) { + print("Plugin cancel error: ${e.message}"); + return Future.error("cancel failed.", stack); + } + } } diff --git a/flutter/flutter/lib/chapter.dart b/flutter/flutter/lib/chapter.dart index cbf7bfc..cdf6b87 100644 --- a/flutter/flutter/lib/chapter.dart +++ b/flutter/flutter/lib/chapter.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Taner Sener + * Copyright (c) 2021-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -51,7 +51,7 @@ class Chapter { String? getEndTime() => this.getStringProperty(Chapter.keyEndTime); /// Returns all tags. - Map? getTags() => this.getProperties(Chapter.keyTags); + Map? getTags() => this.getProperty(Chapter.keyTags); /// Returns the chapter property associated with the key. String? getStringProperty(String key) => this._allProperties?[key]; @@ -59,8 +59,8 @@ class Chapter { /// Returns the chapter property associated with the key. num? getNumberProperty(String key) => this._allProperties?[key]; - /// Returns the chapter properties associated with the key. - dynamic getProperties(String key) => this._allProperties?[key]; + /// Returns the chapter property associated with the key. + dynamic getProperty(String key) => this._allProperties?[key]; /// Returns all properties found. Map? getAllProperties() => this._allProperties; diff --git a/flutter/flutter/lib/ffmpeg_session.dart b/flutter/flutter/lib/ffmpeg_session.dart index 2cbc777..e3a655c 100644 --- a/flutter/flutter/lib/ffmpeg_session.dart +++ b/flutter/flutter/lib/ffmpeg_session.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -49,11 +49,6 @@ class FFmpegSession extends AbstractSession { return session; } - /// Creates a new FFmpeg session from [sessionMap], which includes session - /// fields as map keys. - static FFmpegSession fromMap(Map sessionMap) => - AbstractSession.createFFmpegSessionFromMap(sessionMap); - /// Returns the session specific statistics callback. StatisticsCallback? getStatisticsCallback() => FFmpegKitFactory.getStatisticsCallback(this.getSessionId()); diff --git a/flutter/flutter/lib/ffprobe_session.dart b/flutter/flutter/lib/ffprobe_session.dart index af35a38..42e826d 100644 --- a/flutter/flutter/lib/ffprobe_session.dart +++ b/flutter/flutter/lib/ffprobe_session.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -41,11 +41,6 @@ class FFprobeSession extends AbstractSession { return session; } - /// Creates a new FFprobe session from [sessionMap], which includes session - /// fields as map keys. - static FFprobeSession fromMap(Map sessionMap) => - AbstractSession.createFFprobeSessionFromMap(sessionMap); - /// Returns the session specific complete callback. FFprobeSessionCompleteCallback? getCompleteCallback() => FFmpegKitFactory.getFFprobeSessionCompleteCallback(this.getSessionId()); diff --git a/flutter/flutter/lib/media_information.dart b/flutter/flutter/lib/media_information.dart index 83560f1..1abb89e 100644 --- a/flutter/flutter/lib/media_information.dart +++ b/flutter/flutter/lib/media_information.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -22,7 +22,7 @@ import 'stream_information.dart'; /// Media information class. class MediaInformation { - static const keyMediaProperties = "format"; + static const keyFormatProperties = "format"; static const keyFilename = "filename"; static const keyFormat = "format_name"; static const keyFormatLong = "format_long_name"; @@ -38,40 +38,54 @@ class MediaInformation { MediaInformation(this._allProperties); /// Returns file name. - String? getFilename() => this.getStringProperty(MediaInformation.keyFilename); + String? getFilename() => + this.getStringFormatProperty(MediaInformation.keyFilename); /// Returns format. - String? getFormat() => this.getStringProperty(MediaInformation.keyFormat); + String? getFormat() => + this.getStringFormatProperty(MediaInformation.keyFormat); /// Returns long format. String? getLongFormat() => - this.getStringProperty(MediaInformation.keyFormatLong); + this.getStringFormatProperty(MediaInformation.keyFormatLong); /// Returns duration. - String? getDuration() => this.getStringProperty(MediaInformation.keyDuration); + String? getDuration() => + this.getStringFormatProperty(MediaInformation.keyDuration); /// Returns start time. String? getStartTime() => - this.getStringProperty(MediaInformation.keyStartTime); + this.getStringFormatProperty(MediaInformation.keyStartTime); /// Returns size. - String? getSize() => this.getStringProperty(MediaInformation.keySize); + String? getSize() => this.getStringFormatProperty(MediaInformation.keySize); /// Returns bitrate. - String? getBitrate() => this.getStringProperty(MediaInformation.keyBitRate); + String? getBitrate() => + this.getStringFormatProperty(MediaInformation.keyBitRate); /// Returns all tags. Map? getTags() => - this.getProperties(StreamInformation.keyTags); + this.getFormatProperty(StreamInformation.keyTags); - /// Returns the media property associated with the key. - String? getStringProperty(String key) => this.getMediaProperties()?[key]; + /// Returns the property associated with the key. + String? getStringProperty(String key) => this.getAllProperties()?[key]; - /// Returns the media property associated with the key. - num? getNumberProperty(String key) => this.getMediaProperties()?[key]; + /// Returns the property associated with the key. + num? getNumberProperty(String key) => this.getAllProperties()?[key]; - /// Returns the media properties associated with the key. - dynamic getProperties(String key) => this.getMediaProperties()?[key]; + /// Returns the property associated with the key. + dynamic getProperty(String key) => this.getAllProperties()?[key]; + + /// Returns the format property associated with the key. + String? getStringFormatProperty(String key) => + this.getFormatProperties()?[key]; + + /// Returns the format property associated with the key. + num? getNumberFormatProperty(String key) => this.getFormatProperties()?[key]; + + /// Returns the format property associated with the key. + dynamic getFormatProperty(String key) => this.getFormatProperties()?[key]; /// Returns all streams found as a list. List getStreams() { @@ -102,9 +116,9 @@ class MediaInformation { return list; } - /// Returns all media properties. - Map? getMediaProperties() => - this._allProperties?[keyMediaProperties]; + /// Returns all format properties found. + Map? getFormatProperties() => + this._allProperties?[keyFormatProperties]; /// Returns all properties found, including stream properties. Map? getAllProperties() => this._allProperties; diff --git a/flutter/flutter/lib/media_information_session.dart b/flutter/flutter/lib/media_information_session.dart index c550ca8..472fa1b 100644 --- a/flutter/flutter/lib/media_information_session.dart +++ b/flutter/flutter/lib/media_information_session.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -43,11 +43,6 @@ class MediaInformationSession extends AbstractSession { return session; } - /// Creates a new MediaInformation session from [sessionMap], which includes - /// session fields as map keys. - static MediaInformationSession fromMap(Map sessionMap) => - AbstractSession.createMediaInformationSessionFromMap(sessionMap); - /// Returns the media information extracted in this session. MediaInformation? getMediaInformation() => this._mediaInformation; diff --git a/flutter/flutter/lib/session.dart b/flutter/flutter/lib/session.dart index 7fe16ae..a4796d8 100644 --- a/flutter/flutter/lib/session.dart +++ b/flutter/flutter/lib/session.dart @@ -106,5 +106,5 @@ abstract class Session { bool isMediaInformation(); /// Cancels running the session. - void cancel(); + Future cancel(); } diff --git a/flutter/flutter/lib/src/ffmpeg_kit_factory.dart b/flutter/flutter/lib/src/ffmpeg_kit_factory.dart index bb4529d..d72fca1 100644 --- a/flutter/flutter/lib/src/ffmpeg_kit_factory.dart +++ b/flutter/flutter/lib/src/ffmpeg_kit_factory.dart @@ -17,15 +17,13 @@ * along with FFmpegKit. If not, see . */ -import '../ffmpeg_session.dart'; +import '../abstract_session.dart'; import '../ffmpeg_session_complete_callback.dart'; -import '../ffprobe_session.dart'; import '../ffprobe_session_complete_callback.dart'; import '../log.dart'; import '../log_callback.dart'; import '../log_redirection_strategy.dart'; import '../media_information.dart'; -import '../media_information_session.dart'; import '../media_information_session_complete_callback.dart'; import '../session.dart'; import '../statistics.dart'; @@ -66,12 +64,12 @@ class FFmpegKitFactory { static Session mapToSession(Map sessionMap) { switch (sessionMap["type"]) { case 2: - return FFprobeSession.fromMap(sessionMap); + return AbstractSession.createFFprobeSessionFromMap(sessionMap); case 3: - return MediaInformationSession.fromMap(sessionMap); + return AbstractSession.createMediaInformationSessionFromMap(sessionMap); case 1: default: - return FFmpegSession.fromMap(sessionMap); + return AbstractSession.createFFmpegSessionFromMap(sessionMap); } } @@ -79,12 +77,13 @@ class FFmpegKitFactory { if (sessionMap != null) { switch (sessionMap["type"]) { case 2: - return FFprobeSession.fromMap(sessionMap); + return AbstractSession.createFFprobeSessionFromMap(sessionMap); case 3: - return MediaInformationSession.fromMap(sessionMap); + return AbstractSession.createMediaInformationSessionFromMap( + sessionMap); case 1: default: - return FFmpegSession.fromMap(sessionMap); + return AbstractSession.createFFmpegSessionFromMap(sessionMap); } } else { return null; @@ -100,7 +99,7 @@ class FFmpegKitFactory { } } - static String getVersion() => "4.5.1"; + static String getVersion() => "5.1.0"; static LogRedirectionStrategy? getLogRedirectionStrategy(int? sessionId) => logRedirectionStrategyMap[sessionId]; diff --git a/flutter/flutter/lib/stream_information.dart b/flutter/flutter/lib/stream_information.dart index eb546b6..0af0528 100644 --- a/flutter/flutter/lib/stream_information.dart +++ b/flutter/flutter/lib/stream_information.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -108,7 +108,7 @@ class StreamInformation { /// Returns all tags. Map? getTags() => - this.getProperties(StreamInformation.keyTags); + this.getProperty(StreamInformation.keyTags); /// Returns the stream property associated with the key. String? getStringProperty(String key) => this._allProperties?[key]; @@ -116,8 +116,8 @@ class StreamInformation { /// Returns the stream property associated with the key. num? getNumberProperty(String key) => this._allProperties?[key]; - /// Returns the stream properties associated with the key. - dynamic getProperties(String key) => this._allProperties?[key]; + /// Returns the stream property associated with the key. + dynamic getProperty(String key) => this._allProperties?[key]; /// Returns all properties found. Map? getAllProperties() => this._allProperties; diff --git a/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m b/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m index f9f557e..b616988 100644 --- a/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m +++ b/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -112,30 +112,40 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; - (void)registerGlobalCallbacks { [FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }); }]; [FFmpegKitConfig enableLogCallback: ^(Log* log){ if (self->logsEnabled) { NSDictionary *dictionary = [FFmpegKitFlutterPlugin toLogDictionary:log]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_LOG_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_LOG_CALLBACK_EVENT withDictionary:dictionary]); + }); } }]; [FFmpegKitConfig enableStatisticsCallback:^(Statistics* statistics){ if (self->statisticsEnabled) { NSDictionary *dictionary = [FFmpegKitFlutterPlugin toStatisticsDictionary:statistics]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_STATISTICS_CALLBACK_EVENT withDictionary:dictionary]); + dispatch_async(dispatch_get_main_queue(), ^() { + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_STATISTICS_CALLBACK_EVENT withDictionary:dictionary]); + }); } }]; } @@ -563,7 +573,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFmpegSession - (void)ffmpegSession:(NSArray*)arguments result:(FlutterResult)result { - FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFmpegSession* session = [FFmpegSession create:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } @@ -604,14 +614,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFprobeSession - (void)ffprobeSession:(NSArray*)arguments result:(FlutterResult)result { - FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFprobeSession* session = [FFprobeSession create:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } // MediaInformationSession - (void)mediaInformationSession:(NSArray*)arguments result:(FlutterResult)result { - MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil]; + MediaInformationSession* session = [MediaInformationSession create:arguments withCompleteCallback:nil withLogCallback:nil]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } @@ -632,23 +642,21 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // MediaInformationJsonParser - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; result([FFmpegKitFlutterPlugin toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"Parsing MediaInformation failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); result(nil); } } - (void)mediaInformationJsonParserFromWithError:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; result([FFmpegKitFlutterPlugin toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"Parsing MediaInformation failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); result([FlutterError errorWithCode:@"PARSE_FAILED" message:@"Parsing MediaInformation failed with JSON error." details:nil]); } } diff --git a/flutter/flutter/macos/ffmpeg_kit_flutter.podspec b/flutter/flutter/macos/ffmpeg_kit_flutter.podspec index 083244d..ee93a39 100644 --- a/flutter/flutter/macos/ffmpeg_kit_flutter.podspec +++ b/flutter/flutter/macos/ffmpeg_kit_flutter.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ffmpeg_kit_flutter' - s.version = '4.5.1' + s.version = '5.1.0' s.summary = 'FFmpeg Kit for Flutter' s.description = 'A Flutter plugin for running FFmpeg and FFprobe commands.' s.homepage = 'https://github.com/arthenica/ffmpeg-kit' @@ -23,112 +23,112 @@ Pod::Spec.new do |s| s.subspec 'min' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-min', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-min', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'min-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-min', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-min', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'min-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-min-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-min-gpl', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'min-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-min-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-min-gpl', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'https' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-https', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-https', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'https-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-https', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-https', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'https-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-https-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-https-gpl', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'https-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-https-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-https-gpl', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'audio' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-audio', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-audio', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'audio-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-audio', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-audio', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'video' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-video', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-video', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'video-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-video', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-video', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'full' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-full', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-full', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'full-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-full', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-full', "5.1.LTS" ss.osx.deployment_target = '10.12' end s.subspec 'full-gpl' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-full-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-macos-full-gpl', "5.1" ss.osx.deployment_target = '10.15' end s.subspec 'full-gpl-lts' do |ss| ss.source_files = 'Classes/**/*' ss.public_header_files = 'Classes/**/*.h' - ss.dependency 'ffmpeg-kit-macos-full-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-macos-full-gpl', "5.1.LTS" ss.osx.deployment_target = '10.12' end diff --git a/flutter/flutter/pubspec.yaml b/flutter/flutter/pubspec.yaml index 5af935f..c592e26 100644 --- a/flutter/flutter/pubspec.yaml +++ b/flutter/flutter/pubspec.yaml @@ -3,7 +3,7 @@ description: FFmpeg Kit for Flutter. Supports Android, iOS and macOS platforms. repository: https://github.com/arthenica/ffmpeg-kit issue_tracker: https://github.com/arthenica/ffmpeg-kit/issues homepage: https://github.com/arthenica/ffmpeg-kit -version: 4.5.1 +version: 5.1.0 environment: sdk: ">=2.12.0 <3.0.0" @@ -28,4 +28,4 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - plugin_platform_interface: ^2.0.2 + plugin_platform_interface: ^2.1.3 diff --git a/react-native/README.md b/react-native/README.md index 23ff7dd..fd1a2f1 100644 --- a/react-native/README.md +++ b/react-native/README.md @@ -4,11 +4,13 @@ - Includes both `FFmpeg` and `FFprobe` - Supports - Both `Android` and `iOS` - - FFmpeg `v4.5-dev` releases + - FFmpeg `v5.1.2` - `arm-v7a`, `arm-v7a-neon`, `arm64-v8a`, `x86` and `x86_64` architectures on Android - - `Android API Level 16` or later + - `Android API Level 24` or later + - `API Level 16` on LTS releases - `armv7`, `armv7s`, `arm64`, `arm64-simulator`, `i386`, `x86_64`, `x86_64-mac-catalyst` and `arm64-mac-catalyst` architectures on iOS - - `iOS SDK 10` or later + - `iOS SDK 12.1` or later + - `iOS SDK 10` on LTS releases - Can process Storage Access Framework (SAF) Uris on Android - 25 external libraries @@ -22,7 +24,7 @@ - `bzip2`, `iconv`, `libuuid`, `zlib` system libraries and `AudioToolbox`, `VideoToolbox`, `AVFoundation` system frameworks on iOS - Includes Typescript definitions -- Licensed under LGPL 3.0, can be customized to support GPL v3.0 +- Licensed under `LGPL 3.0` by default, some packages licensed by `GPL v3.0` effectively ### 2. Installation @@ -32,16 +34,16 @@ yarn add ffmpeg-kit-react-native #### 2.1 Packages -`ffmpeg` includes built-in encoders for some popular formats. However, there are certain external libraries that needs +`FFmpeg` includes built-in encoders for some popular formats. However, there are certain external libraries that needs to be enabled in order to encode specific formats/codecs. For example, to encode an `mp3` file you need `lame` or `shine` library enabled. You have to install a `ffmpeg-kit-react-native` package that has at least one of them inside. To encode an `h264` video, you need to install a package with `x264` inside. To encode `vp8` or `vp9` videos, you need a `ffmpeg-kit-react-native` package with `libvpx` inside. -`ffmpeg-kit` provides eight packages that include different sets of external libraries. These packages are -named according to the external libraries included in them. Refer to -[Packages](https://github.com/arthenica/ffmpeg-kit#8-packages) section of the project README to see the names -of those packages and external libraries included in each of them. +`ffmpeg-kit` provides eight packages that include different sets of external libraries. These packages are named +according to the external libraries included. Refer to the +[Packages](https://github.com/arthenica/ffmpeg-kit/wiki/Packages) wiki page to see the names of those +packages and external libraries included in each one of them. ##### 2.1.1 Package Names @@ -184,10 +186,10 @@ the package name you are using. #### 2.4 LTS Releases -`ffmpeg-kit-react-native` is published in two different variants: `Main Release` and `LTS Release`. Both releases -share the same source code but is built with different settings (Architectures, API Level, iOS Min SDK, etc.). Refer to -[LTS Releases](https://github.com/arthenica/ffmpeg-kit#9-lts-releases) section of the project README to see how they -compare to each other. +`ffmpeg-kit-react-native` is published in two variants: `Main Release` and `LTS Release`. Both releases share the +same source code but is built with different settings (Architectures, API Level, iOS Min SDK, etc.). Refer to the +[LTS Releases](https://github.com/arthenica/ffmpeg-kit/wiki/LTS-Releases) wiki page to see how they differ from each +other. ### 3. Using diff --git a/react-native/android/build.gradle b/react-native/android/build.gradle index e00921b..dcb21f2 100644 --- a/react-native/android/build.gradle +++ b/react-native/android/build.gradle @@ -1,11 +1,11 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:7.3.0' } } @@ -26,13 +26,13 @@ def safeExtGet(String prop, String fallback) { } android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { minSdkVersion safeExtGet('ffmpegKitPackage', 'https').contains("-lts") ? 16 : 24 - targetSdkVersion 30 - versionCode 452 - versionName "4.5.2" + targetSdkVersion 31 + versionCode 510 + versionName "5.1.0" } buildTypes { @@ -44,14 +44,13 @@ android { disable 'GradleCompatible' } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } } repositories { mavenCentral() - jcenter() google() def found = false diff --git a/react-native/android/gradle.properties b/react-native/android/gradle.properties index 389aa70..e1fff5b 100644 --- a/react-native/android/gradle.properties +++ b/react-native/android/gradle.properties @@ -1,3 +1,3 @@ android.useAndroidX=true -ffmpegKit.android.main.version=4.5.1-1 -ffmpegKit.android.lts.version=4.5.1-1 +ffmpegKit.android.main.version=5.1 +ffmpegKit.android.lts.version=5.1 diff --git a/react-native/android/gradle/wrapper/gradle-wrapper.properties b/react-native/android/gradle/wrapper/gradle-wrapper.properties index 28ff446..ae04661 100644 --- a/react-native/android/gradle/wrapper/gradle-wrapper.properties +++ b/react-native/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java b/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java index bccdcee..8d7ed2c 100644 --- a/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java +++ b/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java @@ -344,7 +344,7 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule { @ReactMethod public void ffmpegSession(final ReadableArray readableArray, final Promise promise) { - promise.resolve(toMap(new FFmpegSession(toArgumentsArray(readableArray), null, null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS))); + promise.resolve(toMap(FFmpegSession.create(toArgumentsArray(readableArray), null, null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS))); } @ReactMethod @@ -395,14 +395,14 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule { @ReactMethod public void ffprobeSession(final ReadableArray readableArray, final Promise promise) { - promise.resolve(toMap(new FFprobeSession(toArgumentsArray(readableArray), null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS))); + promise.resolve(toMap(FFprobeSession.create(toArgumentsArray(readableArray), null, null, LogRedirectionStrategy.NEVER_PRINT_LOGS))); } // MediaInformationSession @ReactMethod public void mediaInformationSession(final ReadableArray readableArray, final Promise promise) { - promise.resolve(toMap(new MediaInformationSession(toArgumentsArray(readableArray), null, null))); + promise.resolve(toMap(MediaInformationSession.create(toArgumentsArray(readableArray), null, null))); } // MediaInformationJsonParser diff --git a/react-native/ffmpeg-kit-react-native.podspec b/react-native/ffmpeg-kit-react-native.podspec index 7d19f88..653bcf0 100644 --- a/react-native/ffmpeg-kit-react-native.podspec +++ b/react-native/ffmpeg-kit-react-native.podspec @@ -23,112 +23,112 @@ Pod::Spec.new do |s| s.subspec 'min' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-min', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-min', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'min-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-min', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-min', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'min-gpl' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-min-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-min-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'min-gpl-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-min-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-min-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'https' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-https', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-https', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'https-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-https', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-https', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'https-gpl' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-https-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-https-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'https-gpl-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-https-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-https-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'audio' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-audio', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-audio', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'audio-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-audio', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-audio', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'video' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-video', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-video', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'video-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-video', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-video', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'full' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-full', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-full', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'full-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-full', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-full', "5.1.LTS" ss.ios.deployment_target = '10' end s.subspec 'full-gpl' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-full-gpl', "4.5.1" + ss.dependency 'ffmpeg-kit-ios-full-gpl', "5.1" ss.ios.deployment_target = '12.1' end s.subspec 'full-gpl-lts' do |ss| ss.source_files = '**/FFmpegKitReactNativeModule.m', '**/FFmpegKitReactNativeModule.h' - ss.dependency 'ffmpeg-kit-ios-full-gpl', "4.5.1.LTS" + ss.dependency 'ffmpeg-kit-ios-full-gpl', "5.1.LTS" ss.ios.deployment_target = '10' end diff --git a/react-native/ios/FFmpegKitReactNativeModule.m b/react-native/ios/FFmpegKitReactNativeModule.m index 7465cda..04a03b6 100644 --- a/react-native/ios/FFmpegKitReactNativeModule.m +++ b/react-native/ios/FFmpegKitReactNativeModule.m @@ -244,7 +244,7 @@ RCT_EXPORT_METHOD(getArch:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRe // FFmpegSession RCT_EXPORT_METHOD(ffmpegSession:(NSArray*)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFmpegSession* session = [FFmpegSession create:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; resolve([FFmpegKitReactNativeModule toSessionDictionary:session]); } @@ -285,37 +285,35 @@ RCT_EXPORT_METHOD(ffmpegSessionGetStatistics:(int)sessionId resolver:(RCTPromise // FFprobeSession RCT_EXPORT_METHOD(ffprobeSession:(NSArray*)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFprobeSession* session = [FFprobeSession create:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; resolve([FFmpegKitReactNativeModule toSessionDictionary:session]); } // MediaInformationSession RCT_EXPORT_METHOD(mediaInformationSession:(NSArray*)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil]; + MediaInformationSession* session = [MediaInformationSession create:arguments withCompleteCallback:nil withLogCallback:nil]; resolve([FFmpegKitReactNativeModule toSessionDictionary:session]); } // MediaInformationJsonParser RCT_EXPORT_METHOD(mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; resolve([FFmpegKitReactNativeModule toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"MediaInformation parsing failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); resolve(nil); } } RCT_EXPORT_METHOD(mediaInformationJsonParserFromWithError:(NSString*)ffprobeJsonOutput resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - NSError *error; - MediaInformation* mediaInformation = [MediaInformationJsonParser from:ffprobeJsonOutput with:error]; - if (error == nil) { + @try { + MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput]; resolve([FFmpegKitReactNativeModule toMediaInformationDictionary:mediaInformation]); - } else { - NSLog(@"MediaInformation parsing failed: %@.\n", error); + } @catch (NSException *exception) { + NSLog(@"Parsing MediaInformation failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]); reject(@"PARSE_FAILED", @"Parsing MediaInformation failed with JSON error.", nil); } } diff --git a/react-native/package.json b/react-native/package.json index 858566b..42194bd 100644 --- a/react-native/package.json +++ b/react-native/package.json @@ -1,6 +1,6 @@ { "name": "ffmpeg-kit-react-native", - "version": "4.5.2", + "version": "5.1.0", "description": "FFmpeg Kit for React Native", "main": "src/index", "types": "src/index.d.ts", @@ -19,7 +19,7 @@ "ios" ], "repository": "https://github.com/arthenica/ffmpeg-kit", - "author": "ARTHENICA (https://github.com/arthenica)", + "author": "ARTHENICA (https://www.arthenica.com)", "license": "LGPL-3.0", "bugs": { "url": "https://github.com/arthenica/ffmpeg-kit/issues" diff --git a/react-native/src/index.d.ts b/react-native/src/index.d.ts index 8de2b56..9ac8aab 100644 --- a/react-native/src/index.d.ts +++ b/react-native/src/index.d.ts @@ -2,8 +2,6 @@ declare module 'ffmpeg-kit-react-native' { export abstract class AbstractSession implements Session { - protected constructor(); - static createFFmpegSession(argumentsArray: Array, logRedirectionStrategy?: LogRedirectionStrategy): Promise; static createFFmpegSessionFromMap(sessionMap: { [key: string]: any }): FFmpegSession; @@ -212,12 +210,8 @@ declare module 'ffmpeg-kit-react-native' { export class FFmpegSession extends AbstractSession implements Session { - constructor(); - static create(argumentsArray: Array, completeCallback?: FFmpegSessionCompleteCallback, logCallback?: LogCallback, statisticsCallback?: StatisticsCallback, logRedirectionStrategy?: LogRedirectionStrategy): Promise; - static fromMap(sessionMap: { [key: string]: any }): FFmpegSession; - getStatisticsCallback(): StatisticsCallback; getCompleteCallback(): FFmpegSessionCompleteCallback; @@ -266,12 +260,8 @@ declare module 'ffmpeg-kit-react-native' { export class FFprobeSession extends AbstractSession implements Session { - constructor(); - static create(argumentsArray: Array, completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback, logRedirectionStrategy?: LogRedirectionStrategy): Promise; - static fromMap(sessionMap: { [key: string]: any }): FFprobeSession; - getCompleteCallback(): FFprobeSessionCompleteCallback; isFFmpeg(): boolean; @@ -321,7 +311,7 @@ declare module 'ffmpeg-kit-react-native' { export class MediaInformation { - static readonly KEY_MEDIA_PROPERTIES: string; + static readonly KEY_FORMAT_PROPERTIES: string; static readonly KEY_FILENAME: string; static readonly KEY_FORMAT: string; static readonly KEY_FORMAT_LONG: string; @@ -357,9 +347,15 @@ declare module 'ffmpeg-kit-react-native' { getNumberProperty(key: string): number; - getProperties(key: string): Record; + getProperty(key: string): any; - getMediaProperties(): Record; + getStringFormatProperty(key: string): string; + + getNumberFormatProperty(key: string): number; + + getFormatProperty(key: string): any; + + getFormatProperties(): Record; getAllProperties(): Record; @@ -375,12 +371,8 @@ declare module 'ffmpeg-kit-react-native' { export class MediaInformationSession extends AbstractSession implements Session { - constructor(); - static create(argumentsArray: Array, completeCallback?: MediaInformationSessionCompleteCallback, logCallback?: LogCallback): Promise; - static fromMap(sessionMap: { [key: string]: any }): MediaInformationSession; - getMediaInformation(): MediaInformation; setMediaInformation(mediaInformation: MediaInformation): void; @@ -591,7 +583,7 @@ declare module 'ffmpeg-kit-react-native' { getNumberProperty(key): number; - getProperties(key): Record; + getProperty(key): any; getAllProperties(): Record; @@ -627,7 +619,7 @@ declare module 'ffmpeg-kit-react-native' { getNumberProperty(key): number; - getProperties(key): Record; + getProperty(key): any; getAllProperties(): Record; diff --git a/react-native/src/index.js b/react-native/src/index.js index 03241f1..8e167d1 100644 --- a/react-native/src/index.js +++ b/react-native/src/index.js @@ -296,13 +296,6 @@ export class AbstractSession extends Session { */ #logRedirectionStrategy; - /** - * Creates a new abstract session. - */ - constructor() { - super(); - } - /** * Creates a new FFmpeg session. * @@ -1605,12 +1598,12 @@ class FFmpegKitFactory { if (sessionMap !== undefined) { switch (sessionMap.type) { case 2: - return FFprobeSession.fromMap(sessionMap); + return AbstractSession.createFFprobeSessionFromMap(sessionMap); case 3: - return MediaInformationSession.fromMap(sessionMap); + return AbstractSession.createMediaInformationSessionFromMap(sessionMap); case 1: default: - return FFmpegSession.fromMap(sessionMap); + return AbstractSession.createFFmpegSessionFromMap(sessionMap); } } else { return undefined; @@ -1618,7 +1611,7 @@ class FFmpegKitFactory { } static getVersion() { - return "4.5.2"; + return "5.1.0"; } static getLogRedirectionStrategy(sessionId) { @@ -1935,13 +1928,6 @@ class FFmpegKitInitializer { */ export class FFmpegSession extends AbstractSession { - /** - * Creates an empty FFmpeg session. - */ - constructor() { - super(); - } - /** * Creates a new FFmpeg session. * @@ -1963,16 +1949,6 @@ export class FFmpegSession extends AbstractSession { return session; } - /** - * Creates a new FFmpeg session from the given map. - * - * @param sessionMap map that includes session fields as map keys - * @returns FFmpeg session created - */ - static fromMap(sessionMap) { - return AbstractSession.createFFmpegSessionFromMap(sessionMap); - } - /** * Returns the session specific statistics callback. * @@ -2252,13 +2228,6 @@ export class FFprobeKit { */ export class FFprobeSession extends AbstractSession { - /** - * Creates an empty FFprobe session. - */ - constructor() { - super(); - } - /** * Creates a new FFprobe session. * @@ -2278,16 +2247,6 @@ export class FFprobeSession extends AbstractSession { return session; } - /** - * Creates a new FFprobe session from the given map. - * - * @param sessionMap map that includes session fields as map keys - * @returns FFprobe session created - */ - static fromMap(sessionMap) { - return AbstractSession.createFFprobeSessionFromMap(sessionMap); - } - /** * Returns the session specific complete callback. * @@ -2438,7 +2397,7 @@ export class Log { */ export class MediaInformation { - static KEY_MEDIA_PROPERTIES = "format"; + static KEY_FORMAT_PROPERTIES = "format"; static KEY_FILENAME = "filename"; static KEY_FORMAT = "format_name"; static KEY_FORMAT_LONG = "format_long_name"; @@ -2460,7 +2419,7 @@ export class MediaInformation { * @return media file name */ getFilename() { - return this.getStringProperty(MediaInformation.KEY_FILENAME); + return this.getStringFormatProperty(MediaInformation.KEY_FILENAME); } /** @@ -2469,7 +2428,7 @@ export class MediaInformation { * @return media format */ getFormat() { - return this.getStringProperty(MediaInformation.KEY_FORMAT); + return this.getStringFormatProperty(MediaInformation.KEY_FORMAT); } /** @@ -2478,7 +2437,7 @@ export class MediaInformation { * @return media long format */ getLongFormat() { - return this.getStringProperty(MediaInformation.KEY_FORMAT_LONG); + return this.getStringFormatProperty(MediaInformation.KEY_FORMAT_LONG); } /** @@ -2487,7 +2446,7 @@ export class MediaInformation { * @return media duration in "seconds.microseconds" format */ getDuration() { - return this.getStringProperty(MediaInformation.KEY_DURATION); + return this.getStringFormatProperty(MediaInformation.KEY_DURATION); } /** @@ -2496,7 +2455,7 @@ export class MediaInformation { * @return media start time in milliseconds */ getStartTime() { - return this.getStringProperty(MediaInformation.KEY_START_TIME); + return this.getStringFormatProperty(MediaInformation.KEY_START_TIME); } /** @@ -2505,7 +2464,7 @@ export class MediaInformation { * @return media size in bytes */ getSize() { - return this.getStringProperty(MediaInformation.KEY_SIZE); + return this.getStringFormatProperty(MediaInformation.KEY_SIZE); } /** @@ -2514,7 +2473,7 @@ export class MediaInformation { * @return media bitrate in kb/s */ getBitrate() { - return this.getStringProperty(MediaInformation.KEY_BIT_RATE); + return this.getStringFormatProperty(MediaInformation.KEY_BIT_RATE); } /** @@ -2523,7 +2482,7 @@ export class MediaInformation { * @return tags dictionary */ getTags() { - return this.getProperties(MediaInformation.KEY_TAGS); + return this.getFormatProperty(MediaInformation.KEY_TAGS); } /** @@ -2571,58 +2530,103 @@ export class MediaInformation { } /** - * Returns the media property associated with the key. + * Returns the property associated with the key. * * @param key property key - * @return media property as string or undefined if the key is not found + * @return property as string or undefined if the key is not found */ getStringProperty(key) { - let mediaProperties = this.getMediaProperties(); - if (mediaProperties !== undefined) { - return mediaProperties[key]; + let allProperties = this.getAllProperties(); + if (allProperties !== undefined) { + return allProperties[key]; } else { return undefined; } } /** - * Returns the media property associated with the key. + * Returns the property associated with the key. * * @param key property key - * @return media property as number or undefined if the key is not found + * @return property as number or undefined if the key is not found */ getNumberProperty(key) { - let mediaProperties = this.getMediaProperties(); - if (mediaProperties !== undefined) { - return mediaProperties[key]; + let allProperties = this.getAllProperties(); + if (allProperties !== undefined) { + return allProperties[key]; } else { return undefined; } } /** - * Returns the media properties associated with the key. + * Returns the property associated with the key. * - * @param key properties key - * @return media properties as an object or undefined if the key is not found + * @param key property key + * @return property as an object or undefined if the key is not found */ - getProperties(key) { - let mediaProperties = this.getMediaProperties(); - if (mediaProperties !== undefined) { - return mediaProperties[key]; + getProperty(key) { + let allProperties = this.getAllProperties(); + if (allProperties !== undefined) { + return allProperties[key]; } else { return undefined; } } /** - * Returns all media properties. + * Returns the format property associated with the key. * - * @returns an object where media properties can be accessed by property names + * @param key property key + * @return format property as string or undefined if the key is not found */ - getMediaProperties() { + getStringFormatProperty(key) { + let formatProperties = this.getFormatProperties(); + if (formatProperties !== undefined) { + return formatProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns the format property associated with the key. + * + * @param key property key + * @return format property as number or undefined if the key is not found + */ + getNumberFormatProperty(key) { + let formatProperties = this.getFormatProperties(); + if (formatProperties !== undefined) { + return formatProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns the format property associated with the key. + * + * @param key property key + * @return format property as an object or undefined if the key is not found + */ + getFormatProperty(key) { + let formatProperties = this.getFormatProperties(); + if (formatProperties !== undefined) { + return formatProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns all format properties defined. + * + * @returns an object where format properties can be accessed by property names + */ + getFormatProperties() { if (this.#allProperties !== undefined) { - return this.#allProperties.format; + return this.#allProperties[MediaInformation.KEY_FORMAT_PROPERTIES]; } else { return undefined; } @@ -2677,13 +2681,6 @@ export class MediaInformationJsonParser { export class MediaInformationSession extends AbstractSession { #mediaInformation; - /** - * Creates an empty MediaInformationSession. - */ - constructor() { - super(); - } - /** * Creates a new MediaInformationSession session. * @@ -2702,16 +2699,6 @@ export class MediaInformationSession extends AbstractSession { return session; } - /** - * Creates a new MediaInformationSession from the given map. - * - * @param sessionMap map that includes session fields as map keys - * @returns MediaInformationSession created - */ - static fromMap(sessionMap) { - return AbstractSession.createMediaInformationSessionFromMap(sessionMap); - } - /** * Returns the media information extracted in this session. * @@ -3104,7 +3091,7 @@ export class StreamInformation { * @return tags object */ getTags() { - return this.getProperties(StreamInformation.KEY_TAGS); + return this.getProperty(StreamInformation.KEY_TAGS); } /** @@ -3136,12 +3123,12 @@ export class StreamInformation { } /** - * Returns the stream properties associated with the key. + * Returns the stream property associated with the key. * - * @param key properties key - * @return stream properties as an object or undefined if the key is not found + * @param key property key + * @return stream property as an object or undefined if the key is not found */ - getProperties(key) { + getProperty(key) { if (this.#allProperties !== undefined) { return this.#allProperties[key]; } else { @@ -3238,7 +3225,7 @@ export class Chapter { * @return tags object */ getTags() { - return this.getProperties(StreamInformation.KEY_TAGS); + return this.getProperty(StreamInformation.KEY_TAGS); } /** @@ -3270,12 +3257,12 @@ export class Chapter { } /** - * Returns the chapter properties associated with the key. + * Returns the chapter property associated with the key. * - * @param key properties key - * @return chapter properties as an object or undefined if the key is not found + * @param key property key + * @return chapter property as an object or undefined if the key is not found */ - getProperties(key) { + getProperty(key) { if (this.#allProperties !== undefined) { return this.#allProperties[key]; } else {