ffmpeg concat 无需重新编码即可保持音频按一种顺序排列,而不会按另一种顺序排列

ffmpeg concat 无需重新编码即可保持音频按一种顺序排列,而不会按另一种顺序排列

所以我拍了一段视频,用两种方式剪辑,一种是重新编码,一种是没有重新编码,我们把它们称为 R 和 C(剪辑)。我尝试在不重新编码的情况下进行连接,我能够以所有顺序连接视频 <R, R>, <C, C>, <R, C>, <C, R>,但 <R, C> 的声音消失了,我不知道为什么。

我知道我可以用重新编码进行连接,但我的问题是,是否有人知道为什么声音在 <R, C> 中消失,以及如何修复它。以下是 Python 中的一些代码

import os
import json
import subprocess

video_file = 'yourpath/vid.mp4'
# get the time between frames

ffprobe_command = f"ffprobe -v error -select_streams v:0 -show_entries
stream=width,height,r_frame_rate,duration,nb_frames,codec_name -of
json {video_file}"
result = subprocess.run(ffprobe_command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

# Parse the JSON output from ffprobe
json_data = json.loads(result.stdout)

# Extract video information from the JSON data
video_info = {
    'length': int(json_data['streams'][0]['nb_frames']),
    'frames': int(json_data['streams'][0]['nb_frames']),
    'duration_seconds': float(json_data['streams'][0]['duration']),
    'fps': eval(json_data['streams'][0]['r_frame_rate']),
    'codec': json_data['streams'][0]['codec_name'],
    'time_between_frames': 1 / eval(json_data['streams'][0]['r_frame_rate'])
}
# get the time between frames
delta = video_info['time_between_frames']

directory, filename_with_extension = os.path.split(video_file)
filename, extension = os.path.splitext(filename_with_extension)
tag = "_reencode"
new_filename = f"{filename}{tag}{extension}"
reencode_file = directory + "/" + new_filename

tag = "_justcut"
new_filename = f"{filename}{tag}{extension}"
justcut_file = directory + "/" + new_filename

tag = "_concat"
new_filename = f"{filename}{tag}{extension}"
concat_file = directory + "/" + new_filename

start_time = 0.0 + 108 * delta
end_time = start_time + 180 * delta
end_frame = round(end_time / delta)
start_frame = round(start_time / delta)

# Reencode
cmd = [
    "ffmpeg",
    "-i", video_file,
    "-ss", str(start_time),
    "-to", str(end_time),
    # "-c:a", "copy",
    "-c:v", "libx264",
    "-bf", str(0), # no B frames
    "-crf", str(18),  # new
    "-preset", "slow",  # new
    # "-g", str(60), #forces key_frames
    # "-force_key_frames expr:gte(t, n_forced * GOP_LEN_IN_SECONDS)"
    # "-c:v", "mpeg4", #"copy", #"mpeg4"
    # "-q:v", "2",
    "-c:a", "copy",
    # "video_track_timescale", str(90)+"K",
    reencode_file
]
subprocess.run(cmd, check=True)

# Just Cut
cmd = [
    'ffmpeg',
    '-i', video_file,
    '-c', 'copy',
    '-ss', str(start_time),
    '-to', str(end_time),
    justcut_file
]
subprocess.run(cmd, check=True)

# Concat without reencoding
def concatenate_videos_without_reencoding(video1, video2, output_file):
    try:
        # Create a text file listing the videos to concatenate
        with open('input.txt', 'w') as f:
            f.write(f"file '{video1}'\n")
            f.write(f"file '{video2}'\n")

        # Run ffmpeg command to concatenate videos without re-encoding
        # subprocess.run(['ffmpeg', '-f', 'concat', '-safe', '0', '-i', 'input.txt', '-c', 'copy', output_file])

        subprocess.run(
            ['ffmpeg', '-f', 'concat', '-safe', '0', '-i', 'input.txt', '-vcodec', 'copy',
             '-acodec', 'copy', "-strict", "experimental", output_file])

        print(f"Videos concatenated successfully without re-encoding. Output saved to {output_file}")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        # Remove the temporary input file
        if os.path.exists('input.txt'):
            os.remove('input.txt')

如您所见,我尝试了很多方法,但我不知道音频为什么不工作。我尝试过强制两个输入视频在规格、关键帧和 fps 等方面尽可能相似。但似乎都不起作用,有点令人沮丧。

我也尝试使用 mpeg4 和 h264 以及不同的帧速率,但仍然会出现这种情况。

答案1

您可以对要连接的两个输入文件执行 ffprobe 或 mediainfo,然后将结果粘贴到这里吗?对于没有音频的结果文件也可以这样做吗?

当您像这样使用 concat 时,两个输入视频必须具有相同的音频特性。此外,R 视频是否有声音?如果没有,您需要创建一个静音音频流

相关内容