[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 = [
    "-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",
subprocess.run(cmd, check=True)

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

# Concat without reencoding
def concatenate_videos_without_reencoding(video1, video2, output_file):
        # 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