Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3348481
D13021.id43275.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
D13021.id43275.diff
View Options
diff --git a/lib/media/video-utils.js b/lib/media/video-utils.js
--- a/lib/media/video-utils.js
+++ b/lib/media/video-utils.js
@@ -97,14 +97,16 @@
);
const outputPath = `${outputDirectory}${outputFilename}`;
- let quality, speed, scale;
- if (outputCodec === 'h264') {
+ let hardwareAcceleration, quality, speed, scale;
+ if (outputCodec === 'h264_mediacodec') {
+ hardwareAcceleration = 'mediacodec';
const { floor, min, max, log2 } = Math;
const crf = floor(min(5, max(0, log2(inputDuration / 5)))) + 23;
quality = `-crf ${crf}`;
speed = '-preset ultrafast';
scale = `-vf scale=${maxWidth}:${maxHeight}:force_original_aspect_ratio=decrease`;
} else if (outputCodec === 'h264_videotoolbox') {
+ hardwareAcceleration = 'videotoolbox';
quality = '-profile:v baseline';
speed = '-realtime 1';
const { width, height } = inputDimensions;
@@ -120,10 +122,11 @@
}
const ffmpegCommand =
+ `-hwaccel ${hardwareAcceleration} ` +
`-i ${inputPath} ` +
`-c:a copy -c:v ${outputCodec} ` +
`${quality} ` +
- '-vsync 2 -r 30 ' +
+ '-fps_mode cfr -r 30 ' +
`${scale} ` +
`${speed} ` +
'-movflags +faststart ' +
diff --git a/native/android/build.gradle b/native/android/build.gradle
--- a/native/android/build.gradle
+++ b/native/android/build.gradle
@@ -31,7 +31,7 @@
}
ext {
- reactNativeFFmpegPackage = "min-gpl-lts"
+ ffmpegKitPackage = "min-gpl-lts"
}
allprojects {
diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj
--- a/native/ios/Comm.xcodeproj/project.pbxproj
+++ b/native/ios/Comm.xcodeproj/project.pbxproj
@@ -1171,11 +1171,27 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Comm/Pods-Comm-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/ffmpegkit.framework/ffmpegkit",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libavcodec.framework/libavcodec",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libavdevice.framework/libavdevice",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libavfilter.framework/libavfilter",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libavformat.framework/libavformat",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libavutil.framework/libavutil",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libswresample.framework/libswresample",
+ "${PODS_XCFRAMEWORKS_BUILD_DIR}/ffmpeg-kit-ios-min/libswscale.framework/libswscale",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ffmpegkit.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavcodec.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavdevice.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavfilter.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavformat.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavutil.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswresample.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswscale.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1413,7 +1429,6 @@
"\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera\"",
- "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-ffmpeg\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-in-app-message\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-netinfo\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-notifications\"",
@@ -1555,7 +1570,6 @@
"\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera\"",
- "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-ffmpeg\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-in-app-message\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-netinfo\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-notifications\"",
diff --git a/native/ios/Podfile b/native/ios/Podfile
--- a/native/ios/Podfile
+++ b/native/ios/Podfile
@@ -10,7 +10,7 @@
def common_comm_target_pods
pod 'SQLCipher-Amalgamation', :path => '../../node_modules/@commapp/sqlcipher-amalgamation'
pod 'react-native-video/VideoCaching', :podspec => '../node_modules/react-native-video'
- pod 'react-native-ffmpeg/min-lts', :podspec => '../node_modules/react-native-ffmpeg'
+ pod 'ffmpeg-kit-react-native', :subspecs => ['min'], :podspec => '../node_modules/ffmpeg-kit-react-native'
end
post_integrate do |installer|
diff --git a/native/ios/Podfile.lock b/native/ios/Podfile.lock
--- a/native/ios/Podfile.lock
+++ b/native/ios/Podfile.lock
@@ -132,6 +132,10 @@
- React-Core (= 0.70.9)
- React-jsi (= 0.70.9)
- ReactCommon/turbomodule/core (= 0.70.9)
+ - ffmpeg-kit-ios-min (6.0)
+ - ffmpeg-kit-react-native/min (6.0.2):
+ - ffmpeg-kit-ios-min (= 6.0)
+ - React-Core
- fmt (6.2.1)
- glog (0.3.5)
- hermes-engine (0.70.9)
@@ -163,7 +167,6 @@
- MMKVAppExtension (1.3.5):
- MMKVCore (~> 1.3.5)
- MMKVCore (1.3.5)
- - mobile-ffmpeg-min (4.3.1.LTS)
- OLMKit (3.2.14):
- OLMKit/olmc (= 3.2.14)
- OLMKit/olmcpp (= 3.2.14)
@@ -404,9 +407,6 @@
- React
- react-native-camera/RN (3.31.0):
- React
- - react-native-ffmpeg/min-lts (0.4.4):
- - mobile-ffmpeg-min (= 4.3.1.LTS)
- - React
- react-native-in-app-message (1.0.2):
- React
- react-native-netinfo (9.3.7):
@@ -605,6 +605,7 @@
- EXUpdatesInterface (from `../../node_modules/expo-updates-interface/ios`)
- FBLazyVector (from `../../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../../node_modules/react-native/React/FBReactNativeSpec`)
+ - ffmpeg-kit-react-native/min (from `../node_modules/ffmpeg-kit-react-native`)
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../../node_modules/react-native/sdks/hermes/hermes-engine.podspec`)
- libevent (~> 2.1.12)
@@ -629,7 +630,6 @@
- React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../../node_modules/react-native/ReactCommon/logger`)
- react-native-camera (from `../node_modules/react-native-camera`)
- - react-native-ffmpeg/min-lts (from `../node_modules/react-native-ffmpeg`)
- react-native-in-app-message (from `../node_modules/react-native-in-app-message`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
@@ -668,6 +668,7 @@
SPEC REPOS:
trunk:
- DVAssetLoaderDelegate
+ - ffmpeg-kit-ios-min
- fmt
- libaom
- libavif
@@ -678,7 +679,6 @@
- MMKV
- MMKVAppExtension
- MMKVCore
- - mobile-ffmpeg-min
- OpenSSL-Universal
- SDWebImage
- SDWebImageAVIFCoder
@@ -744,6 +744,8 @@
:path: "../../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
:path: "../../node_modules/react-native/React/FBReactNativeSpec"
+ ffmpeg-kit-react-native:
+ :podspec: "../node_modules/ffmpeg-kit-react-native"
glog:
:podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
hermes-engine:
@@ -784,8 +786,6 @@
:path: "../../node_modules/react-native/ReactCommon/logger"
react-native-camera:
:path: "../node_modules/react-native-camera"
- react-native-ffmpeg:
- :podspec: "../node_modules/react-native-ffmpeg"
react-native-in-app-message:
:path: "../node_modules/react-native-in-app-message"
react-native-netinfo:
@@ -885,6 +885,8 @@
EXUpdatesInterface: bffd1ead18f0bab04fa784ca159c115607b8a23c
FBLazyVector: bc76253beb7463b688aa6af913b822ed631de31a
FBReactNativeSpec: 2dfdfdc025c136effd657e62879c66122718030b
+ ffmpeg-kit-ios-min: 4e9a088f4ee9629435960b9d68e54848975f1931
+ ffmpeg-kit-react-native: 3cea88c9c5cfad62e1465279ea7d800dfbba3b00
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
hermes-engine: 918ec5addfbc430c9f443376d739f088b6dc96c3
@@ -898,7 +900,6 @@
MMKV: 506311d0494023c2f7e0b62cc1f31b7370fa3cfb
MMKVAppExtension: 0cb4ebe918cb739fea57f9ed892c050d7c4d2cf6
MMKVCore: 9e2e5fd529b64a9fe15f1a7afb3d73b2e27b4db9
- mobile-ffmpeg-min: d5d22dcef5c8ec56f771258f1f5be245d914f193
OLMKit: a13e1a20579e88d03971c5821360be24949a1a09
OpenSSL-Universal: 84efb8a29841f2764ac5403e0c4119a28b713346
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
@@ -917,7 +918,6 @@
React-jsinspector: d76d32327f21d4f40dcf696231fdbbca60de4711
React-logger: 1b3522f1e05c6360e93df3607a016c39e30a7351
react-native-camera: b5c8c7a71feecfdd5b39f0dbbf6b64b957ed55f2
- react-native-ffmpeg: f9a60452aaa5d478aac205b248224994f3bde416
react-native-in-app-message: f91de5009620af01456531118264c93e249b83ec
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
@@ -959,6 +959,6 @@
Yoga: dc109b79db907f0f589fc423e991b09ec42d2295
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
-PODFILE CHECKSUM: 3ad7489a9ca814690867cca40f302b9432cebe02
+PODFILE CHECKSUM: 08ac12954526f5d7b062d36d800e1b628afe9040
COCOAPODS: 1.14.3
diff --git a/native/media/ffmpeg.js b/native/media/ffmpeg.js
--- a/native/media/ffmpeg.js
+++ b/native/media/ffmpeg.js
@@ -1,6 +1,10 @@
// @flow
-import { RNFFmpeg, RNFFprobe, RNFFmpegConfig } from 'react-native-ffmpeg';
+import {
+ FFmpegKit,
+ FFprobeKit,
+ FFmpegKitConfig,
+} from 'ffmpeg-kit-react-native';
import { getHasMultipleFramesProbeCommand } from 'lib/media/video-utils.js';
import type {
@@ -85,19 +89,26 @@
): Promise<{ rc: number, lastStats: ?FFmpegStatistics }> {
const duration = inputVideoDuration > 0 ? inputVideoDuration : 0.001;
const wrappedCommand = async () => {
- RNFFmpegConfig.resetStatistics();
let lastStats;
if (onTranscodingProgress) {
- RNFFmpegConfig.enableStatisticsCallback(
- (statisticsData: FFmpegStatistics) => {
- lastStats = statisticsData;
- const { time } = statisticsData;
- onTranscodingProgress(time / 1000 / duration);
- },
- );
+ FFmpegKitConfig.enableStatisticsCallback(statisticsObject => {
+ const time = statisticsObject.getTime();
+ onTranscodingProgress(time / 1000 / duration);
+ lastStats = {
+ speed: statisticsObject.getSpeed(),
+ time,
+ size: statisticsObject.getSize(),
+ videoQuality: statisticsObject.getVideoQuality(),
+ videoFrameNumber: statisticsObject.getVideoFrameNumber(),
+ videoFps: statisticsObject.getVideoFps(),
+ bitrate: statisticsObject.getBitrate(),
+ };
+ });
}
- const ffmpegResult = await RNFFmpeg.execute(ffmpegCommand);
- return { ...ffmpegResult, lastStats };
+ const session = await FFmpegKit.execute(ffmpegCommand);
+ const returnCode = await session.getReturnCode();
+ const rc = returnCode.getValue();
+ return { rc, lastStats };
};
return this.queueCommand('process', wrappedCommand);
}
@@ -112,9 +123,10 @@
videoPath: string,
outputPath: string,
): Promise<number> {
- const thumbnailCommand = `-i ${videoPath} -frames 1 -f singlejpeg ${outputPath}`;
- const { rc } = await RNFFmpeg.execute(thumbnailCommand);
- return rc;
+ const thumbnailCommand = `-i ${videoPath} -frames 1 -f mjpeg ${outputPath}`;
+ const session = await FFmpegKit.execute(thumbnailCommand);
+ const returnCode = await session.getReturnCode();
+ return returnCode.getValue();
}
getVideoInfo(path: string): Promise<VideoInfo> {
@@ -123,26 +135,28 @@
}
static async innerGetVideoInfo(path: string): Promise<VideoInfo> {
- const info = await RNFFprobe.getMediaInformation(path);
+ const session = await FFprobeKit.getMediaInformation(path);
+ const info = await session.getMediaInformation();
const videoStreamInfo = FFmpeg.getVideoStreamInfo(info);
const codec = videoStreamInfo?.codec;
const dimensions = videoStreamInfo && videoStreamInfo.dimensions;
- const format = info.format.split(',');
- const duration = info.duration / 1000;
+ const format = info.getFormat().split(',');
+ const duration = info.getDuration();
return { codec, format, dimensions, duration };
}
static getVideoStreamInfo(
info: Object,
): ?{ +codec: string, +dimensions: Dimensions } {
- if (!info.streams) {
+ const streams = info.getStreams();
+ if (!streams) {
return null;
}
- for (const stream of info.streams) {
- if (stream.type === 'video') {
- const codec: string = stream.codec;
- const width: number = stream.width;
- const height: number = stream.height;
+ for (const stream of streams) {
+ if (stream.getType() === 'video') {
+ const codec: string = stream.getCodec();
+ const width: number = stream.getWidth();
+ const height: number = stream.getHeight();
return { codec, dimensions: { width, height } };
}
}
@@ -155,9 +169,11 @@
}
static async innerHasMultipleFrames(path: string): Promise<boolean> {
- await RNFFprobe.execute(getHasMultipleFramesProbeCommand(path));
- const probeOutput = await RNFFmpegConfig.getLastCommandOutput();
- const numFrames = parseInt(probeOutput.lastCommandOutput);
+ const session = await FFprobeKit.execute(
+ getHasMultipleFramesProbeCommand(path),
+ );
+ const probeOutput = await session.getOutput();
+ const numFrames = parseInt(probeOutput);
return numFrames > 1;
}
}
diff --git a/native/media/video-utils.js b/native/media/video-utils.js
--- a/native/media/video-utils.js
+++ b/native/media/video-utils.js
@@ -79,12 +79,9 @@
inputDuration: duration,
inputDimensions: input.dimensions,
outputDirectory: temporaryDirectoryPath,
- // We want ffmpeg to use hardware-accelerated encoders. On iOS we can do
- // this using VideoToolbox, but ffmpeg on Android is still missing
- // MediaCodec encoding support: https://trac.ffmpeg.org/ticket/6407
outputCodec: Platform.select({
ios: 'h264_videotoolbox',
- //android: 'h264_mediacodec',
+ android: 'h264_mediacodec',
default: 'h264',
}),
clientConnectionInfo: {
diff --git a/native/package.json b/native/package.json
--- a/native/package.json
+++ b/native/package.json
@@ -84,6 +84,7 @@
"expo-media-library": "~15.0.0",
"expo-secure-store": "~12.0.0",
"expo-splash-screen": "~0.17.4",
+ "ffmpeg-kit-react-native": "^6.0.2",
"find-root": "^1.1.0",
"invariant": "^2.2.4",
"lib": "0.0.1",
@@ -95,7 +96,6 @@
"react-native": "0.70.9",
"react-native-camera": "^3.31.0",
"react-native-device-info": "^10.3.0",
- "react-native-ffmpeg": "^0.4.4",
"react-native-figma-squircle": "^0.1.2",
"react-native-floating-action": "^1.22.0",
"react-native-fs": "^2.20.0",
diff --git a/patches/react-native-ffmpeg+0.4.4.patch b/patches/react-native-ffmpeg+0.4.4.patch
deleted file mode 100644
--- a/patches/react-native-ffmpeg+0.4.4.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/node_modules/react-native-ffmpeg/android/build.gradle b/node_modules/react-native-ffmpeg/android/build.gradle
-index 32923e4..283b63c 100644
---- a/node_modules/react-native-ffmpeg/android/build.gradle
-+++ b/node_modules/react-native-ffmpeg/android/build.gradle
-@@ -14,6 +14,7 @@ apply plugin: 'com.android.library'
-
- buildscript {
- repositories {
-+ gradlePluginPortal()
- jcenter()
- maven { url 'https://maven.google.com' }
- }
diff --git a/yarn.lock b/yarn.lock
--- a/yarn.lock
+++ b/yarn.lock
@@ -11836,6 +11836,11 @@
biskviit "1.0.1"
encoding "0.1.12"
+ffmpeg-kit-react-native@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-6.0.2.tgz#9eeac96ad89367c99480bd90431391405d4eb73e"
+ integrity sha512-r9uSmahq8TeyIb7fXf3ft+uUXyoeWRFa99+khjo0TAzWO9y0z9wU7eGnab9JLw1MmCB9v64o4yojNluJhVm9nQ==
+
figma-squircle@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/figma-squircle/-/figma-squircle-0.1.2.tgz#fa97de644131d99f2c42a2d8b70d56a36783c234"
@@ -20253,11 +20258,6 @@
resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-10.3.0.tgz#6bab64d84d3415dd00cc446c73ec5e2e61fddbe7"
integrity sha512-/ziZN1sA1REbJTv5mQZ4tXggcTvSbct+u5kCaze8BmN//lbxcTvWsU6NQd4IihLt89VkbX+14IGc9sVApSxd/w==
-react-native-ffmpeg@^0.4.4:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/react-native-ffmpeg/-/react-native-ffmpeg-0.4.4.tgz#9f4dbda53c96078cecbbe83a866d4b535b957131"
- integrity sha512-MUBV3Xvto1Hl049Y9EaOZdjazkK1ixQzCzPEt1o7V2duSOrM2kJ2o/RiC4rSRgapU2uqYRHMZ6X4JJI7y40qXw==
-
react-native-figma-squircle@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/react-native-figma-squircle/-/react-native-figma-squircle-0.1.2.tgz#64973afcfb42a53cc662ac2ccfba73ced7297124"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 23, 2:52 PM (19 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2571263
Default Alt Text
D13021.id43275.diff (17 KB)
Attached To
Mode
D13021: [native] Replace react-native-ffmpeg with ffmpeg-kit-react-native
Attached
Detach File
Event Timeline
Log In to Comment