import * as _ from 'lodash'; import { nanoid } from 'nanoid/non-secure'; import { NativeEventEmitter, NativeModules, Platform, processColor, } from 'react-native'; import { BehaviorSubject, Subscription } from 'rxjs'; import type { MergeVideoParams, VideoMergeCallbackForOnProgress, VideoMergeEvent, VideoMergeRNRejectError, } from './type'; export * from './type'; let debugMode: boolean = false; export function setDebugMode(debug: boolean) { debugMode = debug; } const LINKING_ERROR = `The package 'react-native-video-merger' doesn't seem to be linked. Make sure: \n\n` + Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n'; const VideoMerger = NativeModules.VideoMerger ? NativeModules.VideoMerger : new Proxy( {}, { get() { throw new Error(LINKING_ERROR); }, } ); const eventEmitter = new NativeEventEmitter(VideoMerger); export const eventSubscription = new BehaviorSubject< VideoMergeEvent | undefined >(undefined); eventEmitter.addListener( 'RNVideoSDK:dataFromNative', (eventData: VideoMergeEvent) => { if (debugMode) { console.log('#[SDK] RNVideoSDK:dataFromNative', eventData); } eventSubscription.next(eventData); } ); const __cache__ = { subscription: {} as { [key: string]: Subscription }, }; export function multiply(a: number, b: number): Promise { return VideoMerger.multiply(a, b); } /** * 清理缓存目录 * @returns undefined */ export async function cleanCacheDir() { return await VideoMerger.cleanCacheDir({}); } /** * 开始合并视频 * @param params MergeVideoParams * @returns */ export async function mergeVideos( _params: MergeVideoParams, onProgress?: VideoMergeCallbackForOnProgress ): Promise { const params: Record = _.cloneDeep(_params); if (params.backgroundColor) { params.backgroundColor = processColor(params.backgroundColor); } let eventDataCache: VideoMergeEvent return new Promise(async (resolve, reject) => { const subId = nanoid(); const removeSubscription = () => { __cache__.subscription[subId]?.unsubscribe(); delete __cache__.subscription[subId]; }; const sub: Subscription = eventSubscription.subscribe( (eventData: VideoMergeEvent | undefined) => { if (!eventData) { return; } const { errorCode, progress } = eventData; // check error const hasError = errorCode !== 0; if (hasError) { // removeSubscription(); onProgress && onProgress(1); // reject(eventData); return; } // update progress onProgress && onProgress(progress); // check finished const isFinished = progress === 1; if (isFinished) { // removeSubscription(); // resolve(eventData); } } ); __cache__.subscription[subId] = sub; try { const res = await VideoMerger.mergeVideos(params); if (debugMode) { console.log('#[SDK] mergeVideos res', res); } if (!res.outputFilePath && eventDataCache?.outputFilePath) { res.outputFilePath = eventDataCache?.outputFilePath; } resolve(res); } catch (_error) { const error = _error as unknown as VideoMergeRNRejectError; console.log('###error', error.userInfo); reject(error.userInfo); } removeSubscription(); }); }