You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中用FFmpegKit转MP4为HLS流并传Firebase遇问题求助

问题解决:React Native中FFmpegKit生成多码率HLS流并上传Firebase Storage

错误原因分析

你遇到的「Output with label 'v360p' does not exist...」错误主要来自以下几个问题:

  • 滤镜链仅处理了视频流,但未正确映射音频流,导致var_stream_map中指定的音频轨不存在
  • FFmpeg命令的输出路径、主播放列表名称配置与代码逻辑不匹配
  • 未正确等待FFmpegKit任务执行完成,也未检查执行结果
  • 未创建命令中使用的encoded输出目录,导致文件写入失败
  • 硬编码的码率与定义的resolutions数组参数不一致

修正后的完整实现函数

import FFmpegKit, { ReturnCode } from 'ffmpeg-kit-react-native';
import RNFS from 'react-native-fs';
import { storage } from '../path-to-your-firebase-config'; // 替换为你的Firebase配置路径

export async function convertToHLS(inputFilePath: string, outputFolderPath: string, postDocID: string) {
  try {
    // 定义分辨率与码率配置
    const resolutions = [
      { name: '360p', videoBitrate: '800k', audioBitrate: '128k', resolution: '640:360' },
      { name: '480p', videoBitrate: '1500k', audioBitrate: '128k', resolution: '854:480' },
      { name: '720p', videoBitrate: '3000k', audioBitrate: '128k', resolution: '1280:720' },
      { name: '1080p', videoBitrate: '5000k', audioBitrate: '192k', resolution: '1920:1080' },
      { name: '4K', videoBitrate: '8000k', audioBitrate: '192k', resolution: '3840:2160' }
    ];

    // 创建必要的输出目录
    const encodedDir = `${outputFolderPath}/encoded`;
    await RNFS.mkdir(encodedDir);

    // 构建滤镜链:分割视频流并处理每个分辨率的缩放与补边
    const filterComplexParts = [];
    filterComplexParts.push(`split=${resolutions.length}[v0][v1][v2][v3][v4]`);
    resolutions.forEach((res, idx) => {
      filterComplexParts.push(
        `[v${idx}]scale=${res.resolution}:force_original_aspect_ratio=decrease,pad=${res.resolution}:(ow-iw)/2:(oh-ih)/2[vout${idx}]`
      );
    });
    const filterComplex = filterComplexParts.join(';');

    // 构建多码率流映射参数:所有分辨率复用同一音频轨
    const varStreamMap = resolutions.map((res, idx) => `v:${idx},a:0,name:${res.name}`).join(' ');

    // 构建码率参数,与resolutions配置对齐
    const bitrateParams = [];
    resolutions.forEach((res, idx) => {
      bitrateParams.push(`-b:v:${idx} ${res.videoBitrate}`);
    });
    bitrateParams.push(`-b:a:0 ${resolutions[0].audioBitrate}`); // 音频轨统一配置

    // 拼接完整FFmpeg命令
    const command = [
      `-i ${inputFilePath}`,
      `-filter_complex "${filterComplex}"`,
      ...resolutions.map((_, idx) => `-map "[vout${idx}]"`),
      `-map 0:a`,
      `-c:v libx264`,
      `-c:a aac`,
      `-ar 48000`,
      `-preset medium`,
      ...bitrateParams,
      `-var_stream_map "${varStreamMap}"`,
      `-f hls`,
      `-hls_time 3`,
      `-hls_list_size 0`,
      `-hls_flags independent_segments`,
      `-hls_playlist_type vod`,
      `-master_pl_name master.m3u8`,
      `${encodedDir}/stream-%v.m3u8`
    ].join(' ');

    // 执行命令并校验结果
    const session = await FFmpegKit.executeAsync(command);
    const returnCode = await session.getReturnCode();

    if (!ReturnCode.isSuccess(returnCode)) {
      const errorLog = await session.getAllLogsAsString();
      throw new Error(`FFmpeg执行失败: ${errorLog}`);
    }

    // 遍历输出目录上传所有HLS相关文件到Firebase
    const masterPlaylistPath = `${encodedDir}/master.m3u8`;
    const allFiles = await RNFS.readDir(encodedDir);

    const uploadPromises = allFiles.map(async (file) => {
      const storageRef = storage().ref(`posts/${postDocID}/${file.name}`);
      await storageRef.putFile(file.path);
      return storageRef.getDownloadURL();
    });

    const downloadURLs = await Promise.all(uploadPromises);
    const masterURL = downloadURLs.find(url => url.includes('master.m3u8'));

    return { masterPlaylistURL: masterURL, allDownloadURLs: downloadURLs };

  } catch (error) {
    console.error('HLS转换或上传失败:', error);
    throw error;
  }
}

关键修改说明

  • 滤镜链重构:使用filter_complex正确分割视频流并处理每个分辨率的缩放与补边,避免标签引用错误
  • 音频流复用:所有分辨率流复用原始音频轨,无需为每个流单独处理音频,解决音频轨不存在的问题
  • 参数对齐:使用resolutions数组配置生成码率参数,避免硬编码不一致
  • 目录预处理:提前创建encoded输出目录,确保文件可正常写入
  • 执行校验:等待任务完成并检查返回码,失败时获取错误日志便于排查
  • 完整文件上传:遍历输出目录所有文件(主播放列表+分片+分分辨率播放列表)并全部上传,确保HLS流可正常播放

内容的提问来源于stack exchange,提问作者user20150408

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:13:20