[FFmpeg-user] video concat without reencoding keeps audio in one order but not the other
Adrian Szatmari
artabalt at gmail.com
Wed Oct 11 11:38:08 EEST 2023
So I took a video and cut it two ways, one with reencoding and one
without reencoding, call them R and C (cut). Im trying to do
concatenation without reencoding, and I'm able to concat the video in
all orders <R, R>, <C, C>, <R, C>, <C, R>, but the sound disappears
for <R, C> and I have no idea why.
I know I can concatenate with reencoding, but my question is
specifically if someone knows why the sound drops in <R, C> and maybe
how to fix it. Here is some code in 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")
As you can see I tried a bunch of stuff but I have no clue why the
audio is not working. I've tried to force the two input videos to be
as similar as possible in term of specs and keyframes and fps etc.
Nothing seems to work, kinda frustrating.
I've also tried this with both mpeg4 and h264 and different
framerates, but still get this behavior.
More information about the ffmpeg-user
mailing list