如何在React Native中借助ffmpeg-kit为视频添加背景音乐?
在React Native中用ffmpeg-kit给本地视频添加远程背景音乐
下面是完整的实现方案,包含依赖安装、权限配置和核心代码:
1. 安装依赖
先安装ffmpeg-kit的full包(包含全量编解码器,适配多数音视频处理场景)和文件操作工具:
npm install ffmpeg-kit-react-native-full rn-fetch-blob # 或使用yarn yarn add ffmpeg-kit-react-native-full rn-fetch-blob
2. 配置权限
Android
在android/app/src/main/AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
iOS
在ios/[你的项目名]/Info.plist中添加:
<!-- 允许远程音频下载的网络请求 --> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> <!-- 保存输出视频所需的相册访问权限 --> <key>NSPhotoLibraryUsageDescription</key> <string>需要访问相册以保存合并后的视频</string>
3. 核心代码实现
这个组件会先将远程音频下载到本地临时目录,再通过ffmpeg完成本地视频与音频的合并:
import React, { useState } from 'react'; import { View, Button, Alert, Platform } from 'react-native'; import { FFmpegKit } from 'ffmpeg-kit-react-native'; import RNFetchBlob from 'rn-fetch-blob'; const VideoAudioMerger = () => { const [isProcessing, setIsProcessing] = useState(false); // 替换为你的本地视频实际路径 // 注意:项目根目录的视频需先复制到应用可读写目录(如下示例的DocumentDir/DownloadDir) const localVideoPath = Platform.OS === 'ios' ? `${RNFetchBlob.fs.dirs.DocumentDir}/local-video.mp4` : `${RNFetchBlob.fs.dirs.DownloadDir}/local-video.mp4`; const remoteAudioUrl = 'https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'; const tempAudioPath = `${RNFetchBlob.fs.dirs.CacheDir}/temp-audio.mp4`; const outputVideoPath = `${RNFetchBlob.fs.dirs.DocumentDir}/output-with-audio.mp4`; const mergeMedia = async () => { setIsProcessing(true); try { // 1. 下载远程音频到本地临时缓存 await RNFetchBlob.config({ path: tempAudioPath }).fetch('GET', remoteAudioUrl); // 2. 执行ffmpeg合并命令 // 命令说明: // -i 本地视频 -i 本地音频:指定两个输入源 // -c:v copy:直接复制视频流,跳过编码(大幅提升处理速度) // -c:a aac:将音频编码为AAC(保证多平台兼容性) // -map 0:v:0 -map 1:a:0:取视频的视频流、音频的音频流合并 const ffmpegCommand = `-i "${localVideoPath}" -i "${tempAudioPath}" -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 "${outputVideoPath}"`; const session = await FFmpegKit.execute(ffmpegCommand); const returnCode = await session.getReturnCode(); if (returnCode.isValueSuccess()) { Alert.alert('合并完成', `输出路径:${outputVideoPath}`); } else { const errorLog = await session.getFailStackTrace(); Alert.alert('合并失败', errorLog); } } catch (err) { Alert.alert('错误', err.message); } finally { // 清理临时音频文件 await RNFetchBlob.fs.unlink(tempAudioPath); setIsProcessing(false); } }; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title={isProcessing ? '处理中...' : '合并视频与背景音乐'} onPress={mergeMedia} disabled={isProcessing} /> </View> ); }; export default VideoAudioMerger;
关键补充说明
- 本地视频路径处理:项目根目录的视频无法直接被应用访问,需先将视频复制到应用的可读写目录(如
DocumentDir或DownloadDir),可在App启动时通过文件复制操作实现。 - 音频混合模式:若不想替换原视频音频,而是混合原音频与远程音频,可将ffmpeg命令修改为:
-i "${localVideoPath}" -i "${tempAudioPath}" -filter_complex "[0:a][1:a]amix=inputs=2:duration=longest" -c:v copy "${outputVideoPath}" - 性能调整:
-c:v copy会跳过视频编码,若需要调整视频分辨率、帧率等参数,可移除该选项并指定对应的编码格式与参数。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

