This commit is contained in:
2025-08-28 15:13:40 +09:00
parent 6e64d739ac
commit 6404f4176e
3149 changed files with 738551 additions and 335 deletions
@@ -0,0 +1,15 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
@@ -0,0 +1,3 @@
*.pbxproj -text
# specific for windows script files
*.bat text eol=crlf
+60
View File
@@ -0,0 +1,60 @@
# OSX
#
.DS_Store
# XDE
.expo/
# VSCode
.vscode/
jsconfig.json
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IJ
#
.idea
.gradle
local.properties
android.iml
# Cocoapods
#
example/ios/Pods
# node.js
#
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
# Expo
.expo/*
# generated by bob
lib/
+414
View File
@@ -0,0 +1,414 @@
# FFmpegKit for React Native
### 1. Features
- Includes both `FFmpeg` and `FFprobe`
- Supports
- Both `Android` and `iOS`
- FFmpeg `v6.0`
- `arm-v7a`, `arm-v7a-neon`, `arm64-v8a`, `x86` and `x86_64` architectures on Android
- `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 12.1` or later
- `iOS SDK 10` on LTS releases
- Can process Storage Access Framework (SAF) Uris on Android
- 25 external libraries
`dav1d`, `fontconfig`, `freetype`, `fribidi`, `gmp`, `gnutls`, `kvazaar`, `lame`, `libass`, `libiconv`, `libilbc`, `libtheora`, `libvorbis`, `libvpx`, `libwebp`, `libxml2`, `opencore-amr`, `opus`, `shine`, `snappy`, `soxr`, `speex`, `twolame`, `vo-amrwbenc`, `zimg`
- 4 external libraries with GPL license
`vid.stab`, `x264`, `x265`, `xvidcore`
- `zlib` and `MediaCodec` Android system libraries
- `bzip2`, `iconv`, `libuuid`, `zlib` system libraries and `AudioToolbox`, `VideoToolbox`, `AVFoundation` system frameworks on iOS
- Includes Typescript definitions
- Licensed under `LGPL 3.0` by default, some packages licensed by `GPL v3.0` effectively
### 2. Installation
```sh
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
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. 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
The following table shows all package names and their respective API levels, iOS deployment targets defined in
`ffmpeg-kit-react-native`.
<table>
<thead>
<tr>
<th align="center">Package</th>
<th align="center" colspan="3">Main Release</th>
<th align="center" colspan="3">LTS Release</th>
</tr>
<tr>
<th align="center"></th>
<th align="center">Name</th>
<th align="center">Android<br>API Level</th>
<th align="center">iOS Minimum<br>Deployment Target</th>
<th align="center">Name</th>
<th align="center">Android<br>API Level</th>
<th align="center">iOS Minimum<br>Deployment Target</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">min</td>
<td align="center">min</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">min-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">min-gpl</td>
<td align="center">min-gpl</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">min-gpl-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">https</td>
<td align="center">(*) https</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">https-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">https-gpl</td>
<td align="center">https-gpl</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">https-gpl-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">audio</td>
<td align="center">audio</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">audio-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">video</td>
<td align="center">video</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">video-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">full</td>
<td align="center">full</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">full-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">full-gpl</td>
<td align="center">full-gpl</td>
<td align="center">24</td>
<td align="center">12.1</td>
<td align="center">full-gpl-lts</td>
<td align="center">16</td>
<td align="center">10</td>
</tr>
</tbody>
</table>
(*) - Main `https` package is the default package
#### 2.2 Enabling Packages
Installing `ffmpeg-kit-react-native` enables the `https` package by default. It is possible to enable other
packages using the instructions below.
##### 2.2.1 Enabling a Package on Android
- Edit `android/build.gradle` file and add the package name in `ext.ffmpegKitPackage` variable.
```gradle
ext {
ffmpegKitPackage = "<package name>"
}
```
##### 2.2.2 Enabling a Package on iOS
- Edit `ios/Podfile` file and add the package name as `subspec`. After that run `pod install` again.
```ruby
pod 'ffmpeg-kit-react-native', :subspecs => ['<package name>'], :podspec => '../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec'
```
- Note that if you have `use_native_modules!` in your `Podfile`, specifying a `subspec` may cause the following error.
You can fix it by defining `ffmpeg-kit-react-native` dependency before `use_native_modules!` in your `Podfile`.
```
[!] There are multiple dependencies with different sources for `ffmpeg-kit-react-native` in `Podfile`:
- ffmpeg-kit-react-native (from `../node_modules/ffmpeg-kit-react-native`)
- ffmpeg-kit-react-native/video (from `../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec`)
```
#### 2.3 Enabling LTS Releases
In order to install the `LTS` variant, install the `https-lts` package using instructions in `2.2` or append `-lts` to
the package name you are using.
#### 2.4 LTS Releases
`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
1. Execute FFmpeg commands.
```js
import { FFmpegKit } from 'ffmpeg-kit-react-native';
FFmpegKit.execute('-i file1.mp4 -c:v mpeg4 file2.mp4').then(async (session) => {
const returnCode = await session.getReturnCode();
if (ReturnCode.isSuccess(returnCode)) {
// SUCCESS
} else if (ReturnCode.isCancel(returnCode)) {
// CANCEL
} else {
// ERROR
}
});
```
2. Each `execute` call creates a new session. Access every detail about your execution from the
session created.
```js
FFmpegKit.execute('-i file1.mp4 -c:v mpeg4 file2.mp4').then(async (session) => {
// Unique session id created for this execution
const sessionId = session.getSessionId();
// Command arguments as a single string
const command = session.getCommand();
// Command arguments
const commandArguments = session.getArguments();
// State of the execution. Shows whether it is still running or completed
const state = await session.getState();
// Return code for completed sessions. Will be undefined if session is still running or FFmpegKit fails to run it
const returnCode = await session.getReturnCode()
const startTime = session.getStartTime();
const endTime = await session.getEndTime();
const duration = await session.getDuration();
// Console output generated for this execution
const output = await session.getOutput();
// The stack trace if FFmpegKit fails to run a command
const failStackTrace = await session.getFailStackTrace()
// The list of logs generated for this execution
const logs = await session.getLogs();
// The list of statistics generated for this execution (only available on FFmpegSession)
const statistics = await session.getStatistics();
});
```
3. Execute `FFmpeg` commands by providing session specific `execute`/`log`/`session` callbacks.
```js
FFmpegKit.executeAsync('-i file1.mp4 -c:v mpeg4 file2.mp4', session => {
// CALLED WHEN SESSION IS EXECUTED
}, log => {
// CALLED WHEN SESSION PRINTS LOGS
}, statistics => {
// CALLED WHEN SESSION GENERATES STATISTICS
});
```
4. Execute `FFprobe` commands.
```js
FFprobeKit.execute(ffprobeCommand).then(async (session) => {
// CALLED WHEN SESSION IS EXECUTED
});
```
5. Get media information for a file/url.
```js
FFprobeKit.getMediaInformation(testUrl).then(async (session) => {
const information = await session.getMediaInformation();
if (information === undefined) {
// CHECK THE FOLLOWING ATTRIBUTES ON ERROR
const state = FFmpegKitConfig.sessionStateToString(await session.getState());
const returnCode = await session.getReturnCode();
const failStackTrace = await session.getFailStackTrace();
const duration = await session.getDuration();
const output = await session.getOutput();
}
});
```
6. Stop ongoing FFmpeg operations.
- Stop all sessions
```js
FFmpegKit.cancel();
```
- Stop a specific session
```js
FFmpegKit.cancel(sessionId);
```
7. (Android) Convert Storage Access Framework (SAF) Uris into paths that can be read or written by
`FFmpegKit` and `FFprobeKit`.
- Reading a file:
```js
FFmpegKitConfig.selectDocumentForRead('*/*').then(uri => {
FFmpegKitConfig.getSafParameterForRead(uri).then(safUrl => {
FFmpegKit.executeAsync(`-i ${safUrl} -c:v mpeg4 file2.mp4`);
});
});
```
- Writing to a file:
```js
FFmpegKitConfig.selectDocumentForWrite('video.mp4', 'video/*').then(uri => {
FFmpegKitConfig.getSafParameterForWrite(uri).then(safUrl => {
FFmpegKit.executeAsync(`-i file1.mp4 -c:v mpeg4 ${safUrl}`);
});
});
```
8. Get previous `FFmpeg`, `FFprobe` and `MediaInformation` sessions from the session history.
```js
FFmpegKit.listSessions().then(sessionList => {
sessionList.forEach(async session => {
const sessionId = session.getSessionId();
});
});
FFprobeKit.listFFprobeSessions().then(sessionList => {
sessionList.forEach(async session => {
const sessionId = session.getSessionId();
});
});
FFprobeKit.listMediaInformationSessions().then(sessionList => {
sessionList.forEach(async session => {
const sessionId = session.getSessionId();
});
});
```
9. Enable global callbacks.
- Session type specific Complete Callbacks, called when an async session has been completed
```js
FFmpegKitConfig.enableFFmpegSessionCompleteCallback(session => {
const sessionId = session.getSessionId();
});
FFmpegKitConfig.enableFFprobeSessionCompleteCallback(session => {
const sessionId = session.getSessionId();
});
FFmpegKitConfig.enableMediaInformationSessionCompleteCallback(session => {
const sessionId = session.getSessionId();
});
```
- Log Callback, called when a session generates logs
```js
FFmpegKitConfig.enableLogCallback(log => {
const message = log.getMessage();
});
```
- Statistics Callback, called when a session generates statistics
```js
FFmpegKitConfig.enableStatisticsCallback(statistics => {
const size = statistics.getSize();
});
```
10. Register system fonts and custom font directories.
```js
FFmpegKitConfig.setFontDirectoryList(["/system/fonts", "/System/Library/Fonts", "<folder with fonts>"]);
```
### 4. Test Application
You can see how `FFmpegKit` is used inside an application by running `react-native` test applications developed under
the [FFmpegKit Test](https://github.com/arthenica/ffmpeg-kit-test) project.
### 5. Tips
See [Tips](https://github.com/arthenica/ffmpeg-kit/wiki/Tips) wiki page.
### 6. License
See [License](https://github.com/arthenica/ffmpeg-kit/wiki/License) wiki page.
### 7. Patents
See [Patents](https://github.com/arthenica/ffmpeg-kit/wiki/Patents) wiki page.
@@ -0,0 +1,129 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
}
}
apply plugin: 'com.android.library'
static def safePackageName(String packageName) {
packageName.replace("-lts", "")
}
def safePackageVersion(String packageName) {
def version = project.properties['ffmpegKit.android.main.version']
def ltsVersion = project.properties['ffmpegKit.android.lts.version']
packageName.contains("-lts") ? ltsVersion + ".LTS" : version
}
def safeExtGet(String prop, String fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
android {
if (project.android.hasProperty("namespace")) {
namespace 'com.arthenica.ffmpegkit.reactnative'
}
compileSdkVersion 33
defaultConfig {
minSdkVersion safeExtGet('ffmpegKitPackage', 'https').contains("-lts") ? 16 : 24
targetSdkVersion 33
versionCode 602
versionName "6.0.2"
}
buildTypes {
release {
minifyEnabled false
}
}
lintOptions {
disable 'GradleCompatible'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
repositories {
mavenCentral()
google()
def found = false
def defaultDir = null
def androidSourcesName = 'React Native sources'
if (rootProject.ext.has('reactNativeAndroidRoot')) {
defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
} else {
defaultDir = new File(
projectDir,
'node_modules/react-native/android'
)
}
if (defaultDir.exists()) {
maven {
url defaultDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
found = true
} else {
def parentDir = rootProject.projectDir
1.upto(5, {
if (found) return true
parentDir = parentDir.parentFile
def androidSourcesDir = new File(
parentDir,
'node_modules/react-native'
)
def androidPrebuiltBinaryDir = new File(
parentDir,
'node_modules/react-native/android'
)
if (androidPrebuiltBinaryDir.exists()) {
maven {
url androidPrebuiltBinaryDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
found = true
} else if (androidSourcesDir.exists()) {
maven {
url androidSourcesDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
found = true
}
})
}
if (!found) {
throw new GradleException(
"${project.name}: unable to locate React Native android sources. " +
"Ensure you have you installed React Native as a dependency in your project and try again."
)
}
}
dependencies {
api 'com.facebook.react:react-native:+'
implementation 'com.arthenica:ffmpeg-kit-' + safePackageName(safeExtGet('ffmpegKitPackage', 'https')) + ':' + safePackageVersion(safeExtGet('ffmpegKitPackage', 'https'))
}
@@ -0,0 +1,3 @@
android.useAndroidX=true
ffmpegKit.android.main.version=6.0-2
ffmpegKit.android.lts.version=6.0-2
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
+89
View File
@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arthenica.ffmpegkit.reactnative">
</manifest>
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit.reactnative;
import androidx.annotation.NonNull;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Collections;
import java.util.List;
public class FFmpegKitReactNativePackage implements ReactPackage {
@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
return Collections.singletonList(new FFmpegKitReactNativeModule(reactContext));
}
@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit.reactnative;
import com.arthenica.ffmpegkit.FFmpegKitConfig;
import com.arthenica.ffmpegkit.FFmpegSession;
import com.facebook.react.bridge.Promise;
public class FFmpegSessionExecuteTask implements Runnable {
private final FFmpegSession ffmpegSession;
private final Promise promise;
public FFmpegSessionExecuteTask(final FFmpegSession ffmpegSession, final Promise promise) {
this.ffmpegSession = ffmpegSession;
this.promise = promise;
}
@Override
public void run() {
FFmpegKitConfig.ffmpegExecute(ffmpegSession);
promise.resolve(null);
}
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit.reactnative;
import com.arthenica.ffmpegkit.FFmpegKitConfig;
import com.arthenica.ffmpegkit.FFprobeSession;
import com.facebook.react.bridge.Promise;
public class FFprobeSessionExecuteTask implements Runnable {
private final FFprobeSession ffprobeSession;
private final Promise promise;
public FFprobeSessionExecuteTask(final FFprobeSession ffprobeSession, final Promise promise) {
this.ffprobeSession = ffprobeSession;
this.promise = promise;
}
@Override
public void run() {
FFmpegKitConfig.ffprobeExecute(ffprobeSession);
promise.resolve(null);
}
}
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit.reactnative;
import com.arthenica.ffmpegkit.FFmpegKitConfig;
import com.arthenica.ffmpegkit.MediaInformationSession;
import com.facebook.react.bridge.Promise;
public class MediaInformationSessionExecuteTask implements Runnable {
private final MediaInformationSession mediaInformationSession;
private final int timeout;
private final Promise promise;
public MediaInformationSessionExecuteTask(final MediaInformationSession mediaInformationSession, final int timeout, final Promise promise) {
this.mediaInformationSession = mediaInformationSession;
this.timeout = timeout;
this.promise = promise;
}
@Override
public void run() {
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, timeout);
promise.resolve(null);
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit.reactnative;
import static com.arthenica.ffmpegkit.reactnative.FFmpegKitReactNativeModule.LIBRARY_NAME;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import java.io.IOException;
public class WriteToPipeTask implements Runnable {
private final String inputPath;
private final String namedPipePath;
private final Promise promise;
public WriteToPipeTask(final String inputPath, final String namedPipePath, final Promise promise) {
this.inputPath = inputPath;
this.namedPipePath = namedPipePath;
this.promise = promise;
}
@Override
public void run() {
int rc;
try {
final String asyncCommand = "cat " + inputPath + " > " + namedPipePath;
Log.d(LIBRARY_NAME, String.format("Starting copy %s to pipe %s operation.", inputPath, namedPipePath));
final long startTime = System.currentTimeMillis();
final Process process = Runtime.getRuntime().exec(new String[]{"sh", "-c", asyncCommand});
rc = process.waitFor();
final long endTime = System.currentTimeMillis();
Log.d(LIBRARY_NAME, String.format("Copying %s to pipe %s operation completed with rc %d in %d seconds.", inputPath, namedPipePath, rc, (endTime - startTime) / 1000));
promise.resolve(rc);
} catch (final IOException | InterruptedException e) {
Log.e(LIBRARY_NAME, String.format("Copy %s to pipe %s failed with error.", inputPath, namedPipePath), e);
promise.reject("Copy failed", String.format("Copy %s to pipe %s failed with error.", inputPath, namedPipePath), e);
}
}
}
@@ -0,0 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};
@@ -0,0 +1,135 @@
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
Pod::Spec.new do |s|
s.name = package["name"]
s.version = package["version"]
s.summary = package["description"]
s.homepage = package["homepage"]
s.license = package["license"]
s.authors = package["author"]
s.platform = :ios
s.requires_arc = true
s.static_framework = true
s.source = { :git => "https://github.com/arthenica/ffmpeg-kit.git", :tag => "react.native.v#{s.version}" }
s.default_subspec = 'https'
s.dependency "React-Core"
s.subspec 'min' do |ss|
ss.source_files = '**/FFmpegKitReactNativeModule.m',
'**/FFmpegKitReactNativeModule.h'
ss.dependency 'ffmpeg-kit-ios-min', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.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', "6.0"
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', "6.0.LTS"
ss.ios.deployment_target = '10'
end
end
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import <ffmpegkit/FFmpegKitConfig.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface FFmpegKitReactNativeModule : RCTEventEmitter<RCTBridgeModule>
@end
@@ -0,0 +1,866 @@
/*
* Copyright (c) 2021-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "FFmpegKitReactNativeModule.h"
#import <React/RCTLog.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <ffmpegkit/FFmpegKit.h>
#import <ffmpegkit/FFprobeKit.h>
#import <ffmpegkit/ArchDetect.h>
#import <ffmpegkit/MediaInformation.h>
#import <ffmpegkit/Packages.h>
static NSString *const PLATFORM_NAME = @"ios";
// LOG CLASS
static NSString *const KEY_LOG_SESSION_ID = @"sessionId";
static NSString *const KEY_LOG_LEVEL = @"level";
static NSString *const KEY_LOG_MESSAGE = @"message";
// STATISTICS CLASS
static NSString *const KEY_STATISTICS_SESSION_ID = @"sessionId";
static NSString *const KEY_STATISTICS_VIDEO_FRAME_NUMBER = @"videoFrameNumber";
static NSString *const KEY_STATISTICS_VIDEO_FPS = @"videoFps";
static NSString *const KEY_STATISTICS_VIDEO_QUALITY = @"videoQuality";
static NSString *const KEY_STATISTICS_SIZE = @"size";
static NSString *const KEY_STATISTICS_TIME = @"time";
static NSString *const KEY_STATISTICS_BITRATE = @"bitrate";
static NSString *const KEY_STATISTICS_SPEED = @"speed";
// SESSION CLASS
static NSString *const KEY_SESSION_ID = @"sessionId";
static NSString *const KEY_SESSION_CREATE_TIME = @"createTime";
static NSString *const KEY_SESSION_START_TIME = @"startTime";
static NSString *const KEY_SESSION_COMMAND = @"command";
static NSString *const KEY_SESSION_TYPE = @"type";
static NSString *const KEY_SESSION_MEDIA_INFORMATION = @"mediaInformation";
// SESSION TYPE
static int const SESSION_TYPE_FFMPEG = 1;
static int const SESSION_TYPE_FFPROBE = 2;
static int const SESSION_TYPE_MEDIA_INFORMATION = 3;
// EVENTS
static NSString *const EVENT_LOG_CALLBACK_EVENT = @"FFmpegKitLogCallbackEvent";
static NSString *const EVENT_STATISTICS_CALLBACK_EVENT = @"FFmpegKitStatisticsCallbackEvent";
static NSString *const EVENT_COMPLETE_CALLBACK_EVENT = @"FFmpegKitCompleteCallbackEvent";
extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
@implementation FFmpegKitReactNativeModule {
BOOL logsEnabled;
BOOL statisticsEnabled;
dispatch_queue_t asyncDispatchQueue;
}
RCT_EXPORT_MODULE(FFmpegKitReactNativeModule);
- (instancetype)init {
self = [super init];
if (self) {
logsEnabled = false;
statisticsEnabled = false;
asyncDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self registerGlobalCallbacks];
}
return self;
}
- (NSArray<NSString*>*)supportedEvents {
NSMutableArray *array = [NSMutableArray array];
[array addObject:EVENT_LOG_CALLBACK_EVENT];
[array addObject:EVENT_STATISTICS_CALLBACK_EVENT];
[array addObject:EVENT_COMPLETE_CALLBACK_EVENT];
return array;
}
- (void)registerGlobalCallbacks {
[FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session){
NSDictionary *dictionary = [FFmpegKitReactNativeModule toSessionDictionary:session];
[self sendEventWithName:EVENT_COMPLETE_CALLBACK_EVENT body:dictionary];
}];
[FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session){
NSDictionary *dictionary = [FFmpegKitReactNativeModule toSessionDictionary:session];
[self sendEventWithName:EVENT_COMPLETE_CALLBACK_EVENT body:dictionary];
}];
[FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session){
NSDictionary *dictionary = [FFmpegKitReactNativeModule toSessionDictionary:session];
[self sendEventWithName:EVENT_COMPLETE_CALLBACK_EVENT body:dictionary];
}];
[FFmpegKitConfig enableLogCallback: ^(Log* log){
if (self->logsEnabled) {
NSDictionary *dictionary = [FFmpegKitReactNativeModule toLogDictionary:log];
[self sendEventWithName:EVENT_LOG_CALLBACK_EVENT body:dictionary];
}
}];
[FFmpegKitConfig enableStatisticsCallback:^(Statistics* statistics){
if (self->statisticsEnabled) {
NSDictionary *dictionary = [FFmpegKitReactNativeModule toStatisticsDictionary:statistics];
[self sendEventWithName:EVENT_STATISTICS_CALLBACK_EVENT body:dictionary];
}
}];
}
// AbstractSession
RCT_EXPORT_METHOD(abstractSessionGetEndTime:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
NSDate* endTime = [session getEndTime];
if (endTime == nil) {
resolve(nil);
} else {
resolve([NSNumber numberWithDouble:[endTime timeIntervalSince1970]*1000]);
}
}
}
RCT_EXPORT_METHOD(abstractSessionGetDuration:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
resolve([NSNumber numberWithLong:[session getDuration]]);
}
}
RCT_EXPORT_METHOD(abstractSessionGetAllLogs:(int)sessionId withTimeout:(int)waitTimeout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
int timeout;
if ([FFmpegKitReactNativeModule isValidPositiveNumber:waitTimeout]) {
timeout = waitTimeout;
} else {
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
}
NSArray* allLogs = [session getAllLogsWithTimeout:timeout];
resolve([FFmpegKitReactNativeModule toLogArray:allLogs]);
}
}
RCT_EXPORT_METHOD(abstractSessionGetLogs:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
NSArray* logs = [session getLogs];
resolve([FFmpegKitReactNativeModule toLogArray:logs]);
}
}
RCT_EXPORT_METHOD(abstractSessionGetAllLogsAsString:(int)sessionId withTimeout:(int)waitTimeout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
int timeout;
if ([FFmpegKitReactNativeModule isValidPositiveNumber:waitTimeout]) {
timeout = waitTimeout;
} else {
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
}
NSString* allLogsAsString = [session getAllLogsAsStringWithTimeout:timeout];
resolve(allLogsAsString);
}
}
RCT_EXPORT_METHOD(abstractSessionGetState:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
resolve([FFmpegKitReactNativeModule sessionStateToNumber:[session getState]]);
}
}
RCT_EXPORT_METHOD(abstractSessionGetReturnCode:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
ReturnCode* returnCode = [session getReturnCode];
if (returnCode == nil) {
resolve(nil);
} else {
resolve([NSNumber numberWithInt:[returnCode getValue]]);
}
}
}
RCT_EXPORT_METHOD(abstractSessionGetFailStackTrace:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
resolve([session getFailStackTrace]);
}
}
RCT_EXPORT_METHOD(thereAreAsynchronousMessagesInTransmit:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
resolve([NSNumber numberWithBool:[session thereAreAsynchronousMessagesInTransmit]]);
}
}
// ArchDetect
RCT_EXPORT_METHOD(getArch:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([ArchDetect getArch]);
}
// FFmpegSession
RCT_EXPORT_METHOD(ffmpegSession:(NSArray*)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
FFmpegSession* session = [FFmpegSession create:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
resolve([FFmpegKitReactNativeModule toSessionDictionary:session]);
}
RCT_EXPORT_METHOD(ffmpegSessionGetAllStatistics:(int)sessionId withTimeout:(int)waitTimeout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFmpeg]) {
int timeout;
if ([FFmpegKitReactNativeModule isValidPositiveNumber:waitTimeout]) {
timeout = waitTimeout;
} else {
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
}
NSArray* allStatistics = [(FFmpegSession*)session getAllStatisticsWithTimeout:timeout];
resolve([FFmpegKitReactNativeModule toStatisticsArray:allStatistics]);
} else {
reject(@"NOT_FFMPEG_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(ffmpegSessionGetStatistics:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFmpeg]) {
NSArray* statistics = [(FFmpegSession*)session getStatistics];
resolve([FFmpegKitReactNativeModule toStatisticsArray:statistics]);
} else {
reject(@"NOT_FFMPEG_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
// FFprobeSession
RCT_EXPORT_METHOD(ffprobeSession:(NSArray*)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
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 create:arguments withCompleteCallback:nil withLogCallback:nil];
resolve([FFmpegKitReactNativeModule toSessionDictionary:session]);
}
// MediaInformationJsonParser
RCT_EXPORT_METHOD(mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
@try {
MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput];
resolve([FFmpegKitReactNativeModule toMediaInformationDictionary:mediaInformation]);
} @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) {
@try {
MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput];
resolve([FFmpegKitReactNativeModule toMediaInformationDictionary:mediaInformation]);
} @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);
}
}
// FFmpegKitConfig
RCT_EXPORT_METHOD(enableRedirection:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[self enableLogs];
[self enableStatistics];
[FFmpegKitConfig enableRedirection];
resolve(nil);
}
RCT_EXPORT_METHOD(disableRedirection:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig disableRedirection];
resolve(nil);
}
RCT_EXPORT_METHOD(enableLogs:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[self enableLogs];
resolve(nil);
}
RCT_EXPORT_METHOD(disableLogs:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[self disableLogs];
resolve(nil);
}
RCT_EXPORT_METHOD(enableStatistics:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[self enableStatistics];
resolve(nil);
}
RCT_EXPORT_METHOD(disableStatistics:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[self disableStatistics];
resolve(nil);
}
RCT_EXPORT_METHOD(setFontconfigConfigurationPath:(NSString*)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setFontconfigConfigurationPath:path];
resolve(nil);
}
RCT_EXPORT_METHOD(setFontDirectory:(NSString*)fontDirectoryPath with:(NSDictionary*)fontNameMap resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setFontDirectory:fontDirectoryPath with:fontNameMap];
resolve(nil);
}
RCT_EXPORT_METHOD(setFontDirectoryList:(NSArray*)fontDirectoryList with:(NSDictionary*)fontNameMap resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setFontDirectoryList:fontDirectoryList with:fontNameMap];
resolve(nil);
}
RCT_EXPORT_METHOD(registerNewFFmpegPipe:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitConfig registerNewFFmpegPipe]);
}
RCT_EXPORT_METHOD(closeFFmpegPipe:(NSString*)ffmpegPipePath resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig closeFFmpegPipe:ffmpegPipePath];
resolve(nil);
}
RCT_EXPORT_METHOD(getFFmpegVersion:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitConfig getFFmpegVersion]);
}
RCT_EXPORT_METHOD(isLTSBuild:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([NSNumber numberWithInt:[FFmpegKitConfig isLTSBuild]]);
}
RCT_EXPORT_METHOD(getBuildDate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitConfig getBuildDate]);
}
RCT_EXPORT_METHOD(setEnvironmentVariable:(NSString*)variableName with:(NSString*)variableValue resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setEnvironmentVariable:variableName value:variableValue];
resolve(nil);
}
RCT_EXPORT_METHOD(ignoreSignal:(int)signalValue resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if ((signalValue == SignalInt) || (signalValue == SignalQuit) || (signalValue == SignalPipe) || (signalValue == SignalTerm) || (signalValue == SignalXcpu)) {
resolve(nil);
} else {
reject(@"INVALID_SIGNAL", @"Signal value not supported.", nil);
}
}
RCT_EXPORT_METHOD(ffmpegSessionExecute:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFmpeg]) {
dispatch_async(asyncDispatchQueue, ^{
[FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session];
resolve(nil);
});
} else {
reject(@"NOT_FFMPEG_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(ffprobeSessionExecute:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFprobe]) {
dispatch_async(asyncDispatchQueue, ^{
[FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session];
resolve(nil);
});
} else {
reject(@"NOT_FFPROBE_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(mediaInformationSessionExecute:(int)sessionId withTimeout:(int)waitTimeout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isMediaInformation]) {
int timeout;
if ([FFmpegKitReactNativeModule isValidPositiveNumber:waitTimeout]) {
timeout = waitTimeout;
} else {
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
}
dispatch_async(asyncDispatchQueue, ^{
[FFmpegKitConfig getMediaInformationExecute:(MediaInformationSession*)session withTimeout:timeout];
resolve(nil);
});
} else {
reject(@"NOT_MEDIA_INFORMATION_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(asyncFFmpegSessionExecute:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFmpeg]) {
[FFmpegKitConfig asyncFFmpegExecute:(FFmpegSession*)session];
resolve(nil);
} else {
reject(@"NOT_FFMPEG_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(asyncFFprobeSessionExecute:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isFFprobe]) {
[FFmpegKitConfig asyncFFprobeExecute:(FFprobeSession*)session];
resolve(nil);
} else {
reject(@"NOT_FFPROBE_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(asyncMediaInformationSessionExecute:(int)sessionId withTimeout:(int)waitTimeout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isMediaInformation]) {
int timeout;
if ([FFmpegKitReactNativeModule isValidPositiveNumber:waitTimeout]) {
timeout = waitTimeout;
} else {
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
}
[FFmpegKitConfig asyncGetMediaInformationExecute:(MediaInformationSession*)session withTimeout:timeout];
resolve(nil);
} else {
reject(@"NOT_MEDIA_INFORMATION_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
RCT_EXPORT_METHOD(getLogLevel:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([NSNumber numberWithInt:[FFmpegKitConfig getLogLevel]]);
}
RCT_EXPORT_METHOD(setLogLevel:(int)level resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setLogLevel:level];
resolve(nil);
}
RCT_EXPORT_METHOD(getSessionHistorySize:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([NSNumber numberWithInt:[FFmpegKitConfig getSessionHistorySize]]);
}
RCT_EXPORT_METHOD(setSessionHistorySize:(int)sessionHistorySize resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setSessionHistorySize:sessionHistorySize];
resolve(nil);
}
RCT_EXPORT_METHOD(getSession:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
resolve([FFmpegKitReactNativeModule toSessionDictionary:session]);
}
}
RCT_EXPORT_METHOD(getLastSession:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionDictionary:[FFmpegKitConfig getLastSession]]);
}
RCT_EXPORT_METHOD(getLastCompletedSession:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionDictionary:[FFmpegKitConfig getLastCompletedSession]]);
}
RCT_EXPORT_METHOD(getSessions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionArray:[FFmpegKitConfig getSessions]]);
}
RCT_EXPORT_METHOD(clearSessions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig clearSessions];
resolve(nil);
}
RCT_EXPORT_METHOD(getSessionsByState:(int)sessionState resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionArray:[FFmpegKitConfig getSessionsByState:sessionState]]);
}
RCT_EXPORT_METHOD(getLogRedirectionStrategy:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule logRedirectionStrategyToNumber:[FFmpegKitConfig getLogRedirectionStrategy]]);
}
RCT_EXPORT_METHOD(setLogRedirectionStrategy:(int)logRedirectionStrategy resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKitConfig setLogRedirectionStrategy:logRedirectionStrategy];
resolve(nil);
}
RCT_EXPORT_METHOD(messagesInTransmit:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([NSNumber numberWithInt:[FFmpegKitConfig messagesInTransmit:sessionId]]);
}
RCT_EXPORT_METHOD(getPlatform:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve(PLATFORM_NAME);
}
RCT_EXPORT_METHOD(writeToPipe:(NSString*)inputPath onPipe:(NSString*)namedPipePath resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
dispatch_async(asyncDispatchQueue, ^{
NSLog(@"Starting copy %@ to pipe %@ operation.\n", inputPath, namedPipePath);
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath: inputPath];
if (fileHandle == nil) {
NSLog(@"Failed to open file %@.\n", inputPath);
reject(@"Copy failed", [NSString stringWithFormat:@"Failed to open file %@.", inputPath], nil);
return;
}
NSFileHandle *pipeHandle = [NSFileHandle fileHandleForWritingAtPath: namedPipePath];
if (pipeHandle == nil) {
NSLog(@"Failed to open pipe %@.\n", namedPipePath);
reject(@"Copy failed", [NSString stringWithFormat:@"Failed to open pipe %@.", namedPipePath], nil);
[fileHandle closeFile];
return;
}
int BUFFER_SIZE = 4096;
unsigned long readBytes = 0;
unsigned long totalBytes = 0;
double startTime = CACurrentMediaTime();
@try {
[fileHandle seekToFileOffset: 0];
do {
NSData *data = [fileHandle readDataOfLength:BUFFER_SIZE];
readBytes = [data length];
if (readBytes > 0) {
totalBytes += readBytes;
[pipeHandle writeData:data];
}
} while (readBytes > 0);
double endTime = CACurrentMediaTime();
NSLog(@"Copying %@ to pipe %@ operation completed successfully. %lu bytes copied in %f seconds.\n", inputPath, namedPipePath, totalBytes, (endTime - startTime)/1000);
resolve(0);
} @catch (NSException *e) {
NSLog(@"Copy failed %@.\n", [e reason]);
reject(@"Copy failed", [NSString stringWithFormat:@"Copy %@ to %@ failed with error %@.", inputPath, namedPipePath, [e reason]], nil);
} @finally {
[fileHandle closeFile];
[pipeHandle closeFile];
}
});
}
RCT_EXPORT_METHOD(selectDocument:(BOOL)writable title:(NSString*)title type:(NSString*)type array:(NSArray*)extraTypes resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
reject(@"Not Supported", @"Not supported on iOS platform.", nil);
}
RCT_EXPORT_METHOD(getSafParameter:(NSString*)uriString mode:(NSString*)openMode resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
reject(@"Not Supported", @"Not supported on iOS platform.", nil);
}
// FFmpegKit
RCT_EXPORT_METHOD(cancel:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKit cancel];
resolve(nil);
}
RCT_EXPORT_METHOD(cancelSession:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[FFmpegKit cancel:sessionId];
resolve(nil);
}
RCT_EXPORT_METHOD(getFFmpegSessions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionArray:[FFmpegKit listSessions]]);
}
// FFprobeKit
RCT_EXPORT_METHOD(getFFprobeSessions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionArray:[FFprobeKit listFFprobeSessions]]);
}
RCT_EXPORT_METHOD(getMediaInformationSessions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FFmpegKitReactNativeModule toSessionArray:[FFprobeKit listMediaInformationSessions]]);
}
// MediaInformationSession
RCT_EXPORT_METHOD(getMediaInformation:(int)sessionId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:sessionId];
if (session == nil) {
reject(@"SESSION_NOT_FOUND", @"Session not found.", nil);
} else {
if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
resolve([FFmpegKitReactNativeModule toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]);
} else {
reject(@"NOT_MEDIA_INFORMATION_SESSION", @"A session is found but it does not have the correct type.", nil);
}
}
}
// Packages
RCT_EXPORT_METHOD(getPackageName:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([Packages getPackageName]);
}
RCT_EXPORT_METHOD(getExternalLibraries:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([Packages getExternalLibraries]);
}
RCT_EXPORT_METHOD(uninit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve(nil);
}
- (void)enableLogs {
logsEnabled = true;
}
- (void)disableLogs {
logsEnabled = false;
}
- (void)enableStatistics {
statisticsEnabled = true;
}
- (void)disableStatistics {
statisticsEnabled = false;
}
+ (BOOL)requiresMainQueueSetup {
return NO;
}
+ (NSDictionary*)toSessionDictionary:(id<Session>) session {
if (session != nil) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
dictionary[KEY_SESSION_ID] = [NSNumber numberWithLong: [session getSessionId]];
dictionary[KEY_SESSION_CREATE_TIME] = [NSNumber numberWithDouble:[[session getCreateTime] timeIntervalSince1970]*1000];
dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithDouble:[[session getStartTime] timeIntervalSince1970]*1000];
dictionary[KEY_SESSION_COMMAND] = [session getCommand];
if ([session isFFmpeg]) {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG];
} else if ([session isFFprobe]) {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE];
} else if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitReactNativeModule toMediaInformationDictionary:[mediaInformationSession getMediaInformation]];
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION];
}
return dictionary;
} else {
return nil;
}
}
+ (NSDictionary*)toLogDictionary:(Log*)log {
if (log != nil) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
dictionary[KEY_LOG_SESSION_ID] = [NSNumber numberWithLong: [log getSessionId]];
dictionary[KEY_LOG_LEVEL] = [NSNumber numberWithInt: [log getLevel]];
dictionary[KEY_LOG_MESSAGE] = [log getMessage];
return dictionary;
} else {
return nil;
}
}
+ (NSDictionary*)toStatisticsDictionary:(Statistics*)statistics {
if (statistics != nil) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
dictionary[KEY_STATISTICS_SESSION_ID] = [NSNumber numberWithLong: [statistics getSessionId]];
dictionary[KEY_STATISTICS_VIDEO_FRAME_NUMBER] = [NSNumber numberWithInt: [statistics getVideoFrameNumber]];
dictionary[KEY_STATISTICS_VIDEO_FPS] = [NSNumber numberWithFloat: [statistics getVideoFps]];
dictionary[KEY_STATISTICS_VIDEO_QUALITY] = [NSNumber numberWithFloat: [statistics getVideoQuality]];
dictionary[KEY_STATISTICS_SIZE] = [NSNumber numberWithLong: [statistics getSize]];
dictionary[KEY_STATISTICS_TIME] = [NSNumber numberWithDouble: [statistics getTime]];
dictionary[KEY_STATISTICS_BITRATE] = [NSNumber numberWithDouble: [statistics getBitrate]];
dictionary[KEY_STATISTICS_SPEED] = [NSNumber numberWithDouble: [statistics getSpeed]];
return dictionary;
} else {
return nil;
}
}
+ (NSDictionary*)toMediaInformationDictionary:(MediaInformation*)mediaInformation {
if (mediaInformation != nil) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
NSDictionary* allProperties = [mediaInformation getAllProperties];
if (allProperties != nil) {
for(NSString *key in [allProperties allKeys]) {
dictionary[key] = [allProperties objectForKey:key];
}
}
return dictionary;
} else {
return nil;
}
}
+ (NSArray*)toLogArray:(NSArray*)logs {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < [logs count]; i++) {
Log* log = [logs objectAtIndex:i];
[array addObject: [FFmpegKitReactNativeModule toLogDictionary:log]];
}
return array;
}
+ (NSArray*)toStatisticsArray:(NSArray*)statisticsArray {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < [statisticsArray count]; i++) {
Statistics* statistics = [statisticsArray objectAtIndex:i];
[array addObject: [FFmpegKitReactNativeModule toStatisticsDictionary:statistics]];
}
return array;
}
+ (NSArray*)toSessionArray:(NSArray*)sessions {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < [sessions count]; i++) {
AbstractSession* session = (AbstractSession*)[sessions objectAtIndex:i];
[array addObject: [FFmpegKitReactNativeModule toSessionDictionary:session]];
}
return array;
}
+ (NSNumber*)sessionStateToNumber:(SessionState)sessionState {
switch (sessionState) {
case SessionStateCreated:
return [NSNumber numberWithInt:0];
case SessionStateRunning:
return [NSNumber numberWithInt:1];
case SessionStateFailed:
return [NSNumber numberWithInt:2];
case SessionStateCompleted:
default:
return [NSNumber numberWithInt:3];
}
}
+ (NSNumber*)logRedirectionStrategyToNumber:(LogRedirectionStrategy)logRedirectionStrategy {
switch (logRedirectionStrategy) {
case LogRedirectionStrategyAlwaysPrintLogs:
return [NSNumber numberWithInt:0];
case LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined:
return [NSNumber numberWithInt:1];
case LogRedirectionStrategyPrintLogsWhenGlobalCallbackNotDefined:
return [NSNumber numberWithInt:2];
case LogRedirectionStrategyPrintLogsWhenSessionCallbackNotDefined:
return [NSNumber numberWithInt:3];
case LogRedirectionStrategyNeverPrintLogs:
default:
return [NSNumber numberWithInt:4];
}
}
+ (BOOL)isValidPositiveNumber:(int)value {
if (value >= 0) {
return true;
} else {
return false;
}
}
@end
@@ -0,0 +1,293 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
5E555C0D2413F4C50049A1A2 /* FFmpegKitReactNativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* FFmpegKitReactNativeModule.m */; };
F4FF95D7245B92E800C19C63 /* FFmpegKitReactNativeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* FFmpegKitReactNativeModule.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
58B511D91A9E6C8500147676 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libFFmpegKitReactNativeModule.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFFmpegKitReactNativeModule.a; sourceTree = BUILT_PRODUCTS_DIR; };
B3E7B5891CC2AC0600A0062D /* FFmpegKitReactNativeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFmpegKitReactNativeModule.m; sourceTree = "<group>"; };
F4FF95D5245B92E700C19C63 /* FFmpegKitReactNativeModule-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FFmpegKitReactNativeModule-Bridging-Header.h"; sourceTree = "<group>"; };
F4FF95D6245B92E800C19C63 /* FFmpegKitReactNativeModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FFmpegKitReactNativeModule.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
58B511D81A9E6C8500147676 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134814211AA4EA7D00B7C361 /* Products */ = {
isa = PBXGroup;
children = (
134814201AA4EA6300B7C361 /* libFFmpegKitReactNativeModule.a */,
);
name = Products;
sourceTree = "<group>";
};
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
F4FF95D6245B92E800C19C63 /* FFmpegKitReactNativeModule.swift */,
B3E7B5891CC2AC0600A0062D /* FFmpegKitReactNativeModule.m */,
F4FF95D5245B92E700C19C63 /* FFmpegKitReactNativeModule-Bridging-Header.h */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
58B511DA1A9E6C8500147676 /* FFmpegKitReactNativeModule */ = {
isa = PBXNativeTarget;
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "FFmpegKitReactNativeModule" */;
buildPhases = (
58B511D71A9E6C8500147676 /* Sources */,
58B511D81A9E6C8500147676 /* Frameworks */,
58B511D91A9E6C8500147676 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = FFmpegKitReactNativeModule;
productName = RCTDataManager;
productReference = 134814201AA4EA6300B7C361 /* libFFmpegKitReactNativeModule.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
58B511D31A9E6C8500147676 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0920;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
58B511DA1A9E6C8500147676 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "FFmpegKitReactNativeModule" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 58B511D21A9E6C8500147676;
productRefGroup = 58B511D21A9E6C8500147676;
projectDirPath = "";
projectRoot = "";
targets = (
58B511DA1A9E6C8500147676 /* FFmpegKitReactNativeModule */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
58B511D71A9E6C8500147676 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F4FF95D7245B92E800C19C63 /* FFmpegKitReactNativeModule.swift in Sources */,
B3E7B58A1CC2AC0600A0062D /* FFmpegKitReactNativeModule.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
58B511ED1A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
58B511EE1A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
58B511F01A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
"$(SRCROOT)/../../react-native/React/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = FFmpegKitReactNativeModule;
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "FFmpegKitReactNativeModule-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
58B511F11A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
"$(SRCROOT)/../../react-native/React/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = FFmpegKitReactNativeModule;
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "FFmpegKitReactNativeModule-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "FFmpegKitReactNativeModule" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511ED1A9E6C8500147676 /* Debug */,
58B511EE1A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "FFmpegKitReactNativeModule" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511F01A9E6C8500147676 /* Debug */,
58B511F11A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
}
+107
View File
@@ -0,0 +1,107 @@
{
"name": "ffmpeg-kit-react-native",
"version": "6.0.2",
"description": "FFmpeg Kit for React Native",
"main": "src/index",
"types": "src/index.d.ts",
"react-native": "src/index",
"source": "src/index",
"scripts": {
"test": "jest",
"lint": "eslint \"**/*.{js,ts,tsx}\"",
"release": "release-it"
},
"keywords": [
"react-native",
"android",
"ffmpeg",
"ffmpeg-kit",
"ios"
],
"repository": "https://github.com/arthenica/ffmpeg-kit",
"author": "ARTHENICA <open-source@arthenica.com> (https://www.arthenica.com)",
"license": "LGPL-3.0",
"bugs": {
"url": "https://github.com/arthenica/ffmpeg-kit/issues"
},
"homepage": "https://github.com/arthenica/ffmpeg-kit",
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"devDependencies": {
"@commitlint/config-conventional": "^17.7.0",
"@react-native-community/eslint-config": "^2.0.0",
"@release-it/conventional-changelog": "^7.0.0",
"@types/jest": "^29.5.4",
"@types/react": "^16.9.19",
"@types/react-native": "^0.62.13",
"commitlint": "^17.7.1",
"eslint": "^8.48.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.6.4",
"pod-install": "^0.1.39",
"prettier": "^3.0.2",
"react": "^16.13.1",
"react-native": "^0.63.4",
"release-it": "^16.1.5"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
},
"jest": {
"preset": "react-native"
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"release-it": {
"git": {
"commitMessage": "chore: release ${version}",
"tagName": "v${version}"
},
"npm": {
"publish": true
},
"github": {
"release": true
},
"plugins": {
"@release-it/conventional-changelog": {
"preset": "angular"
}
}
},
"eslintConfig": {
"root": true,
"extends": [
"@react-native-community",
"prettier"
],
"rules": {
"prettier/prettier": [
"error",
{
"quoteProps": "consistent",
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false
}
]
}
},
"eslintIgnore": [
"node_modules/"
],
"prettier": {
"quoteProps": "consistent",
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false
}
}
+628
View File
@@ -0,0 +1,628 @@
declare module 'ffmpeg-kit-react-native' {
export abstract class AbstractSession implements Session {
static createFFmpegSession(argumentsArray: Array<string>, logRedirectionStrategy?: LogRedirectionStrategy): Promise<FFmpegSession>;
static createFFmpegSessionFromMap(sessionMap: { [key: string]: any }): FFmpegSession;
static createFFprobeSession(argumentsArray: Array<string>, logRedirectionStrategy?: LogRedirectionStrategy): Promise<FFprobeSession>;
static createFFprobeSessionFromMap(sessionMap: { [key: string]: any }): FFprobeSession;
static createMediaInformationSession(argumentsArray: Array<string>): Promise<MediaInformationSession>;
static createMediaInformationSessionFromMap(sessionMap: { [key: string]: any }): MediaInformationSession;
getLogCallback(): LogCallback;
getSessionId(): number;
getCreateTime(): Date;
getStartTime(): Date;
getEndTime(): Promise<Date>;
getDuration(): Promise<number>;
getArguments(): Array<string>;
getCommand(): string;
getAllLogs(waitTimeout ?: number): Promise<Array<Log>>;
getLogs(): Promise<Array<Log>>;
getAllLogsAsString(waitTimeout?: number): Promise<string>;
getLogsAsString(): Promise<string>;
getOutput(): Promise<string>;
getState(): Promise<SessionState>;
getReturnCode(): Promise<ReturnCode>;
getFailStackTrace(): Promise<string>;
getLogRedirectionStrategy(): LogRedirectionStrategy;
thereAreAsynchronousMessagesInTransmit(): Promise<boolean>;
isFFmpeg(): boolean;
isFFprobe(): boolean;
isMediaInformation(): boolean;
cancel(): Promise<void>;
}
export class ArchDetect {
static getArch(): Promise<string>;
}
export type FFmpegSessionCompleteCallback = (session: FFmpegSession) => void;
export type FFprobeSessionCompleteCallback = (session: FFprobeSession) => void;
export type MediaInformationSessionCompleteCallback = (session: MediaInformationSession) => void;
export class FFmpegKit {
static execute(command: string): Promise<FFmpegSession>;
static executeWithArguments(commandArguments: string[]): Promise<FFmpegSession>;
static executeAsync(command: string, completeCallback?: FFmpegSessionCompleteCallback, logCallback?: LogCallback, statisticsCallback?: StatisticsCallback): Promise<FFmpegSession>;
static executeWithArgumentsAsync(commandArguments: string[], completeCallback?: FFmpegSessionCompleteCallback, logCallback?: LogCallback, statisticsCallback?: StatisticsCallback): Promise<FFmpegSession>;
static cancel(sessionId?: number): Promise<void>;
static listSessions(): Promise<FFmpegSession[]>;
}
export class FFmpegKitConfig {
static init(): Promise<void>;
static uninit(): Promise<void>;
static enableRedirection(): Promise<void>;
static disableRedirection(): Promise<void>;
static setFontconfigConfigurationPath(path: string): Promise<void>;
static setFontDirectory(path: string, mapping?: { [key: string]: string }): Promise<void>;
static setFontDirectoryList(fontDirectoryList: string[], mapping?: { [key: string]: string }): Promise<void>;
static registerNewFFmpegPipe(): Promise<string>;
static closeFFmpegPipe(ffmpegPipePath: string): Promise<void>;
static getFFmpegVersion(): Promise<string>;
static getVersion(): Promise<string>;
static isLTSBuild(): Promise<boolean>;
static getBuildDate(): Promise<string>;
static setEnvironmentVariable(name: string, value: string): Promise<void>;
static ignoreSignal(signal: Signal): Promise<void>;
static ffmpegExecute(session: FFmpegSession): Promise<void>;
static ffprobeExecute(session: FFprobeSession): Promise<void>;
static getMediaInformationExecute(session: MediaInformationSession, waitTimeout?: number): Promise<void>;
static asyncFFmpegExecute(session: FFmpegSession): Promise<void>;
static asyncFFprobeExecute(session: FFprobeSession): Promise<void>;
static asyncGetMediaInformationExecute(session: MediaInformationSession, waitTimeout?: number): Promise<void>;
static enableLogCallback(logCallback: LogCallback): void;
static enableStatisticsCallback(statisticsCallback: StatisticsCallback): void;
static enableFFmpegSessionCompleteCallback(completeCallback: FFmpegSessionCompleteCallback): void;
static getFFmpegSessionCompleteCallback(): FFmpegSessionCompleteCallback;
static enableFFprobeSessionCompleteCallback(completeCallback: FFprobeSessionCompleteCallback): void;
static getFFprobeSessionCompleteCallback(): FFprobeSessionCompleteCallback;
static enableMediaInformationSessionCompleteCallback(completeCallback: MediaInformationSessionCompleteCallback): void;
static getMediaInformationSessionCompleteCallback(): MediaInformationSessionCompleteCallback;
static getLogLevel(): Level;
static setLogLevel(level: Level): Promise<void>;
static getSafParameterForRead(uriString: String): Promise<string>;
static getSafParameterForWrite(uriString: String): Promise<string>;
static getSafParameter(uriString: String, openMode: String): Promise<string>;
static getSessionHistorySize(): Promise<number>;
static setSessionHistorySize(sessionHistorySize: number): Promise<void>;
static getSession(sessionId: number): Promise<Session>;
static getLastSession(): Promise<Session>;
static getLastCompletedSession(): Promise<Session>;
static getSessions(): Promise<Session[]>;
static clearSessions(): Promise<void>;
static getFFmpegSessions(): Promise<FFmpegSession[]>;
static getFFprobeSessions(): Promise<FFprobeSession[]>;
static getMediaInformationSessions(): Promise<MediaInformationSession[]>;
static getSessionsByState(state): Promise<Session[]>;
static getLogRedirectionStrategy(): LogRedirectionStrategy;
static setLogRedirectionStrategy(logRedirectionStrategy: LogRedirectionStrategy);
static messagesInTransmit(sessionId: number): Promise<number>;
static sessionStateToString(state): string;
static parseArguments(command: string): string[];
static argumentsToString(commandArguments: string[]): string;
static enableLogs(): Promise<void>;
static disableLogs(): Promise<void>;
static enableStatistics(): Promise<void>;
static disableStatistics(): Promise<void>;
static getPlatform(): Promise<string>;
static writeToPipe(inputPath: string, pipePath: string): Promise<number>;
static selectDocumentForRead(type?: string, extraTypes?: string[]): Promise<string>;
static selectDocumentForWrite(title?: string, type?: string, extraTypes?: string[]): Promise<string>;
}
export class FFmpegSession extends AbstractSession implements Session {
static create(argumentsArray: Array<string>, completeCallback?: FFmpegSessionCompleteCallback, logCallback?: LogCallback, statisticsCallback?: StatisticsCallback, logRedirectionStrategy?: LogRedirectionStrategy): Promise<FFmpegSession>;
getStatisticsCallback(): StatisticsCallback;
getCompleteCallback(): FFmpegSessionCompleteCallback;
getAllStatistics(waitTimeout?: number): Promise<Array<Statistics>>;
getStatistics(): Promise<Array<Statistics>>;
getLastReceivedStatistics(): Promise<Statistics>;
isFFmpeg(): boolean;
isFFprobe(): boolean;
isMediaInformation(): boolean;
}
export class FFprobeKit {
static execute(command: string): Promise<FFprobeSession>;
static executeWithArguments(commandArguments: string[]): Promise<FFprobeSession>;
static executeAsync(command: string, completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback): Promise<FFprobeSession>;
static executeWithArgumentsAsync(commandArguments: string[], completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback): Promise<FFprobeSession>;
static getMediaInformation(path: string, waitTimeout?: number): Promise<MediaInformationSession>;
static getMediaInformationFromCommand(command: string, waitTimeout?: number): Promise<MediaInformationSession>;
static getMediaInformationFromCommandArguments(commandArguments: string[], waitTimeout?: number): Promise<MediaInformationSession>;
static getMediaInformationAsync(path: string, completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback, waitTimeout?: number): Promise<MediaInformationSession>;
static getMediaInformationFromCommandAsync(command: string, completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback, waitTimeout?: number): Promise<MediaInformationSession>;
static getMediaInformationFromCommandArgumentsAsync(commandArguments: string[], completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback, waitTimeout?: number): Promise<MediaInformationSession>;
static listFFprobeSessions(): Promise<FFprobeSession[]>;
static listMediaInformationSessions(): Promise<MediaInformationSession[]>;
}
export class FFprobeSession extends AbstractSession implements Session {
static create(argumentsArray: Array<string>, completeCallback?: FFprobeSessionCompleteCallback, logCallback?: LogCallback, logRedirectionStrategy?: LogRedirectionStrategy): Promise<FFprobeSession>;
getCompleteCallback(): FFprobeSessionCompleteCallback;
isFFmpeg(): boolean;
isFFprobe(): boolean;
isMediaInformation(): boolean;
}
export class Level {
static readonly AV_LOG_STDERR: number;
static readonly AV_LOG_QUIET: number;
static readonly AV_LOG_PANIC: number;
static readonly AV_LOG_FATAL: number;
static readonly AV_LOG_ERROR: number;
static readonly AV_LOG_WARNING: number;
static readonly AV_LOG_INFO: number;
static readonly AV_LOG_VERBOSE: number;
static readonly AV_LOG_DEBUG: number;
static readonly AV_LOG_TRACE: number;
static levelToString(number: number): string;
}
export class Log {
constructor(sessionId: number, level: number, message: String);
getSessionId(): number;
getLevel(): number;
getMessage(): String;
}
export type LogCallback = (log: Log) => void;
export enum LogRedirectionStrategy {
ALWAYS_PRINT_LOGS = 0,
PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED = 1,
PRINT_LOGS_WHEN_GLOBAL_CALLBACK_NOT_DEFINED = 2,
PRINT_LOGS_WHEN_SESSION_CALLBACK_NOT_DEFINED = 3,
NEVER_PRINT_LOGS = 4
}
export class MediaInformation {
static readonly KEY_FORMAT_PROPERTIES: string;
static readonly KEY_FILENAME: string;
static readonly KEY_FORMAT: string;
static readonly KEY_FORMAT_LONG: string;
static readonly KEY_START_TIME: string;
static readonly KEY_DURATION: string;
static readonly KEY_SIZE: string;
static readonly KEY_BIT_RATE: string;
static readonly KEY_TAGS: string;
constructor(properties: Record<string, any>);
getFilename(): string;
getFormat(): string;
getLongFormat(): string;
getDuration(): number;
getStartTime(): string;
getSize(): string;
getBitrate(): string;
getTags(): Record<string, any>;
getStreams(): Array<StreamInformation>;
getChapters(): Array<Chapter>;
getStringProperty(key: string): string;
getNumberProperty(key: string): number;
getProperty(key: string): any;
getStringFormatProperty(key: string): string;
getNumberFormatProperty(key: string): number;
getFormatProperty(key: string): any;
getFormatProperties(): Record<string, any>;
getAllProperties(): Record<string, any>;
}
export class MediaInformationJsonParser {
static from(ffprobeJsonOutput: string): Promise<MediaInformation>;
static fromWithError(ffprobeJsonOutput: string): Promise<MediaInformation>;
}
export class MediaInformationSession extends AbstractSession implements Session {
static create(argumentsArray: Array<string>, completeCallback?: MediaInformationSessionCompleteCallback, logCallback?: LogCallback): Promise<MediaInformationSession>;
getMediaInformation(): MediaInformation;
setMediaInformation(mediaInformation: MediaInformation): void;
getCompleteCallback(): MediaInformationSessionCompleteCallback;
isFFmpeg(): boolean;
isFFprobe(): boolean;
isMediaInformation(): boolean;
}
export class Packages {
static getPackageName(): Promise<string>;
static getExternalLibraries(): Promise<string[]>;
}
export class ReturnCode {
static readonly SUCCESS: number;
static readonly CANCEL: number;
constructor(value: number);
static isSuccess(returnCode: ReturnCode): boolean;
static isCancel(returnCode: ReturnCode): boolean;
getValue(): number;
isValueSuccess(): boolean;
isValueError(): boolean;
isValueCancel(): boolean;
}
export interface Session {
getLogCallback(): LogCallback;
getSessionId(): number;
getCreateTime(): Date;
getStartTime(): Date;
getEndTime(): Promise<Date>;
getDuration(): Promise<number>;
getArguments(): Array<String>;
getCommand(): String;
getAllLogs(waitTimeout ?: number): Promise<Array<Log>>;
getLogs(): Promise<Array<Log>>;
getAllLogsAsString(waitTimeout?: number): Promise<string>;
getLogsAsString(): Promise<string>;
getOutput(): Promise<string>;
getState(): Promise<SessionState>;
getReturnCode(): Promise<ReturnCode>;
getFailStackTrace(): Promise<string>;
getLogRedirectionStrategy(): LogRedirectionStrategy;
thereAreAsynchronousMessagesInTransmit(): Promise<boolean>;
isFFmpeg(): boolean;
isFFprobe(): boolean;
isMediaInformation(): boolean;
cancel(): Promise<void>;
}
export enum SessionState {
CREATED = 0,
RUNNING = 1,
FAILED = 2,
COMPLETED = 3
}
export enum Signal {
SIGINT = 2,
SIGQUIT = 3,
SIGPIPE = 13,
SIGTERM = 15,
SIGXCPU = 24
}
export class Statistics {
constructor(sessionId: number, videoFrameNumber: number, videoFps: number, videoQuality: number, size: number, time: number, bitrate: number, speed: number);
getSessionId(): number;
setSessionId(sessionId: number): void;
getVideoFrameNumber(): number;
setVideoFrameNumber(videoFrameNumber: number): void;
getVideoFps(): number;
setVideoFps(videoFps: number): void;
getVideoQuality(): number;
setVideoQuality(videoQuality: number): void;
getSize(): number;
setSize(size: number): void;
getTime(): number;
setTime(time: number): void;
getBitrate(): number;
setBitrate(bitrate: number): void;
getSpeed(): number;
setSpeed(speed: number): void;
}
export type StatisticsCallback = (statistics: Statistics) => void;
export class StreamInformation {
static readonly KEY_INDEX: string;
static readonly KEY_TYPE: string;
static readonly KEY_CODEC: string;
static readonly KEY_CODEC_LONG: string;
static readonly KEY_FORMAT: string;
static readonly KEY_WIDTH: string;
static readonly KEY_HEIGHT: string;
static readonly KEY_BIT_RATE: string;
static readonly KEY_SAMPLE_RATE: string;
static readonly KEY_SAMPLE_FORMAT: string;
static readonly KEY_CHANNEL_LAYOUT: string;
static readonly KEY_SAMPLE_ASPECT_RATIO: string;
static readonly KEY_DISPLAY_ASPECT_RATIO: string;
static readonly KEY_AVERAGE_FRAME_RATE: string;
static readonly KEY_REAL_FRAME_RATE: string;
static readonly KEY_TIME_BASE: string;
static readonly KEY_CODEC_TIME_BASE: string;
static readonly KEY_TAGS: string;
constructor(properties: Record<string, any>);
getIndex(): number;
getType(): string;
getCodec(): string;
getCodecLong(): string;
getFormat(): string;
getWidth(): number;
getHeight(): number;
getBitrate(): string;
getSampleRate(): string;
getSampleFormat(): string;
getChannelLayout(): string;
getSampleAspectRatio(): string;
getDisplayAspectRatio(): string;
getAverageFrameRate(): string;
getRealFrameRate(): string;
getTimeBase(): string;
getCodecTimeBase(): string;
getTags(): Record<string, any>;
getStringProperty(key): string;
getNumberProperty(key): number;
getProperty(key): any;
getAllProperties(): Record<string, any>;
}
export class Chapter {
static readonly KEY_ID: string;
static readonly KEY_TIME_BASE: string;
static readonly KEY_START: string;
static readonly KEY_START_TIME: string;
static readonly KEY_END: string;
static readonly KEY_END_TIME: string;
static readonly KEY_TAGS: string;
constructor(properties: Record<string, any>);
getId(): number;
getTimeBase(): string;
getStart(): number;
getStartTime(): string;
getEnd(): number;
getEndTime(): string;
getTags(): Record<string, any>;
getStringProperty(key): string;
getNumberProperty(key): number;
getProperty(key): any;
getAllProperties(): Record<string, any>;
}
}
File diff suppressed because it is too large Load Diff