使用FFmpeg将多个不同时长视频统一转为58秒的技术问题咨询
使用FFmpeg将多个不同时长视频统一转为58秒的技术问题咨询
嘿,我明白你的困扰了——你想把一堆不同时长的视频都转成58秒,但因为不知道每个视频的原始时长,所以没法确定setpts和atempo里该填什么数值,手动一个个试肯定不现实对吧?
先给你理清楚FFmpeg这两个参数的逻辑:
假设某个视频的原始时长是T秒,要压缩到58秒的话,视频和音频的播放速度都需要调整为 T/58 倍:
setpts=PTS/(****/58)里的****就是视频的原始时长T,替换后就是setpts=PTS/(T/58),这样视频的播放速度会变成原来的T/58倍,时长就会被压缩到58秒- 对应的
atempo=*****/58里的*****同样是原始时长T,也就是atempo=T/58,保证音频和视频速度同步,不会出现音画错位
但问题在于你没法提前知道每个视频的T,这里给你推荐一个自动批量处理的脚本方案,不用手动查每个视频的时长:
步骤1:用FFprobe获取视频时长(FFmpeg自带工具)
如果你想单独查某个视频的时长,可以用这个命令:
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 video1.mp4
它会输出视频的精确时长(比如125.32秒)
步骤2:批量处理脚本(适用于Linux/macOS的Bash脚本)
把下面的代码保存成batch_resize.sh,放在视频所在的目录里,运行后会自动处理所有.mp4文件:
#!/bin/bash # 遍历当前目录下所有mp4视频 for input_file in *.mp4; do # 获取视频原始时长(保留两位小数) raw_duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input_file" | awk '{printf "%.2f", $0}') # 计算变速倍率:原始时长 / 目标时长58 speed_ratio=$(echo "scale=4; $raw_duration / 58" | bc) # 生成输出文件名(比如video1.mp4 → output_video1.mp4) output_file="output_${input_file}" # 执行FFmpeg转换命令 ffmpeg -i "$input_file" -filter_complex "setpts=PTS/$speed_ratio;atempo=$speed_ratio" "$output_file" done
运行前记得给脚本加执行权限:chmod +x batch_resize.sh,然后直接运行./batch_resize.sh就行。
额外注意事项
- 如果是Windows环境,可以用PowerShell写类似的脚本,核心逻辑还是先获取时长再计算变速比例
- 如果变速比例超过2倍或者低于0.5倍,
atempo可能会导致音质失真,这时可以换成rubberband滤镜(需要你的FFmpeg编译时包含这个组件),把atempo=$speed_ratio改成rubberband=tempo=$speed_ratio,音质会好很多 - 建议先拿一个视频测试,确认输出时长和音画同步都没问题后,再批量处理所有视频
备注:内容来源于stack exchange,提问作者Mena




