使用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
相关产品推荐
相关产品推荐

