是否可以使用 ffmpeg 加速视频和音频,而不改变音频音调?

是否可以使用 ffmpeg 加速视频和音频,而不改变音频音调?

有没有一种相对简单的方法来加速视频(mp4,带有 aac 编码音频),比如说“x1.25”或“x1.3”,同时保持原始音频-视频同步,而且还保留音频的原始音调?

我读过一些关于将音轨提取到单独文件中,然后使用rubberband降低音高所需值的讨论,然后使用 ffmpeg 加速合并音频视频轨道,这会将音频音高再次提高到原始水平。然而,这似乎有点不确定,因为rubberband似乎使用八度音阶数作为提高或降低音高的参数,这可能并不总是与视频完美一致,因为音符/八度音阶具有特定的比率。而且,这很麻烦。

那么,有没有更简单的方法单独使用 ffmpeg?

答案1

可以使用 ffmpgeg 和复杂的过滤器来完成:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mkv

文档:https://trac.ffmpeg.org/wiki/How%20to%20speed%20up%20/%20slow%20down%20a%20video

如果您想将速度乘以 2,上述命令有效。如果您想乘以任意值<x>,参数将变为:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=<1/x>*PTS[v];[0:a]atempo=<x>[a]" -map "[v]" -map "[a]" output.mkv

例如,如果您想乘以 1.15,命令是:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.87*PTS[v];[0:a]atempo=1.15[a]" -map "[v]" -map "[a]" output.mkv

答案2

例如,您可以通过以下步骤将视频速度提高 2.5 倍:

ffmpeg -i "input_video.mp4" -vf "setpts=(PTS-STARTPTS)/2.5" -af atempo=2.5 "input_video_2.5X.mp4"

为了方便起见,您可以使用以下 bash 脚本(例如convert_video.sh):

#!/bin/bash

# Arguments
FILE_RAW=$1
SPEED_FACTOR=${2:-1.0} # Default is 1.0 X speed

# Prepare variables
BASE_PATH=$(dirname $(readlink -f $FILE_RAW))
FILENAME_EXT="$(basename "${FILE_RAW}")"
FILENAME_ONLY="${FILENAME_EXT%.*}"
EXT_ONLY="${FILENAME_EXT#*.}"
FILENAME_ONLY_PATH="${BASE_PATH}/${FILENAME_ONLY}"

# Speed up/slow down video
ffmpeg -i "${FILENAME_ONLY_PATH}.${EXT_ONLY}" -vf "setpts=(PTS-STARTPTS)/${SPEED_FACTOR}" -af atempo=$SPEED_FACTOR "${FILENAME_ONLY_PATH}_${SPEED_FACTOR}X.${EXT_ONLY}"

笔记:使脚本可执行:chmod +x convert_video.sh

用法(输出文件:<PATH_TO_INPUT_VIDEO>_<OPTIONAL_SPEED>X.mp4

. <PATH_TO_THIS_SCRIPT>/convert_video.sh <PATH_TO_INPUT_VIDEO> <OPTIONAL_SPEED>

示例 1:将视频加速至 2.5 倍(输出~/Videos/input_video_2.5X.mp4:)

. ~/convert_video.sh ~/Videos/input_video.mp4 2.5

示例 2:将视频速度减慢至 0.5 倍(输出~/Videos/input_video_0.5X.mp4:)

. ~/convert_video.sh ~/Videos/input_video.mp4 0.5

希望能帮助到你。

答案3

我使用的代码。

speed_change(){
    input=$1
    output=$2
    a_speed=$3
    v_speed=$(awk -v a_speed=$a_speed 'BEGIN{print 1/a_speed}')
    echo -e "\nSpeed up ${a_speed}X, para to atempo is ${a_speed}, para to setpts is ${v_speed}.\n"
    ffmpeg -i $input -c:v hevc_videotoolbox -vf "setpts=$v_speed*PTS" -af atempo=$a_speed $output
}

相关内容