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

使用Node.js在后端实现上传视频fps/码率调整 支持144p到240p等画质切换

实现方案:Node.js后端视频转码与动态画质切换

前置准备

  • 服务器先安装FFmpeg工具,它是视频处理的核心依赖,各系统安装命令示例:
    Ubuntu/Debian:apt install ffmpeg
    CentOS:yum install ffmpeg
    Windows直接下载FFmpeg二进制文件并配置到系统环境变量即可
  • Node.js项目安装ffmpeg封装库:npm install fluent-ffmpeg

核心转码逻辑实现

首先预设画质档位配置,统一管理不同分辨率对应的fps、码率参数:

const qualityProfiles = [
  {
    name: '144p',
    resolution: '256x144',
    fps: 24,
    videoBitrate: '200k',
    audioBitrate: '64k'
  },
  {
    name: '240p',
    resolution: '426x240',
    fps: 24,
    videoBitrate: '400k',
    audioBitrate: '96k'
  },
  // 可按需扩展360p、480p、720p等更多档位
]

单档位转码函数示例:

const ffmpeg = require('fluent-ffmpeg');
const path = require('path');

/**
 * 视频转码为指定画质档位
 * @param {string} inputPath 源视频本地存储路径
 * @param {string} outputDir 转码后文件输出目录
 * @param {object} profile 画质档位配置项
 * @returns {Promise} 转码完成返回输出文件路径
 */
function transcodeSingleProfile(inputPath, outputDir, profile) {
  return new Promise((resolve, reject) => {
    const outputFileName = `${path.parse(inputPath).name}_${profile.name}.mp4`
    const outputPath = path.join(outputDir, outputFileName)
    ffmpeg(inputPath)
      .videoCodec('libx264') // 采用H.264编码兼容性最高
      .audioCodec('aac')
      .size(profile.resolution)
      .fps(profile.fps)
      .videoBitrate(profile.videoBitrate)
      .audioBitrate(profile.audioBitrate)
      .outputOptions('-g', `${profile.fps * 2}`) // 固定关键帧间隔,方便后续做码率切换
      .on('end', () => resolve(outputPath))
      .on('error', (err) => reject(err))
      .save(outputPath)
  })
}

动态画质切换实现

  • 视频上传完成后触发异步批量转码任务,调用上述函数把源视频转码为所有预设档位的文件,按统一规则命名存储
  • 要实现无感知自动切换,建议转码时直接生成HLS(m3u8)切片格式,生成包含所有档位码率信息的主播放列表,前端播放器可根据当前网速自动切换档位,也支持用户手动选择,HLS转码示例:
function transcodeToHLS(inputPath, outputDir, profile) {
  return new Promise((resolve, reject) => {
    const outputPath = path.join(outputDir, `${profile.name}/index.m3u8`)
    ffmpeg(inputPath)
      .videoCodec('libx264')
      .audioCodec('aac')
      .size(profile.resolution)
      .fps(profile.fps)
      .videoBitrate(profile.videoBitrate)
      .audioBitrate(profile.audioBitrate)
      .outputOptions([
        '-hls_time 10', // 单个切片时长10秒
        '-hls_list_size 0',
        '-f hls'
      ])
      .on('end', () => resolve(outputPath))
      .on('error', (err) => reject(err))
      .save(outputPath)
  })
}

注意事项

  • 视频转码属于CPU密集型任务,高并发场景下必须用消息队列异步处理转码任务,不要在同步接口里执行转码逻辑,避免阻塞主业务
  • 建议限制同时运行的转码进程数,防止服务器资源被占满
  • 转码前先读取源视频的原始参数,如果源视频本身画质低于目标档位,不需要向上转码,避免浪费资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:15:04