1

I have a problem with video editing and unsynchronized sound.

What I'd like to achieve:

a) I have a TV tuner, with recording ability. So I have a long .mts file.

b) The file consists of both movie, and commercials. I'd like to cut all the commercials out, and get a movie in .mp4 file (h264, or h265 - it does not matter that much).

--- Part 1 ---

What I do right now:

  1. I get the .mts file, and check it in VLC player. I do it to find the time moments, when commercials start and stop.
  2. I cut the .mts file into pieces, using the command:

ffmpeg -ss <START_MOMENT> -i <FILE> -t <DURATION> -c copy <OUTFILE>.mts > /dev/null 2>&1

In this way, I usually end up with three parts of the video I'd like to achieve.

  1. Having the separated parts (all in the .mts format), I concatenate them:

ffmpeg -f concat -safe 0 -i toconcat.txt -c copy <DEST_FILE>.mts

  1. Then, as the final step, I encode (and, thus, shrink) the file:

ffmpeg -i <CONCATENATED_FILE>.mts -c:v libx264 -preset fast -crf 25 -c:a aac -b:a 128k <TARGET_VIDEO>.mp4

The problem is: in the final .mp4 file, audio is out of sync. After each "junction", the audio gets (more or less) ahead of video. Sometimes the problem is barely noticable, and sometimes it is very annoying.

--- Part 2 ---

I have also thought about some alternative way to solve the problem of "picking up" video fragments of the .mts file:

  1. Find out the frames numbers of video fragments (without commercials).

I could do it by:

a) add frames numbers to the video

ffmpeg -i <INPUT_FILE> -vf "drawtext=fontfile=Arial.ttf:text='%{frame_num}':start_number=0:x=(w-tw)/2:y=h-(2*lh):fontcolor=white:fontsize=50:" -c:a copy <OUT_FILE>

b) check the numbers in some video player

  1. Use MLT framework to make a movie from the original .mts file, by using the found fragments (identified by the frame numbers).

I'm not sure, which method would be the best in order to obtain the video without commercials, and with properly synchronized audio.

1 Answer 1

1

bash script, concat filter

#!/bin/bash
f="/tmp/in.mp4"
o="/tmp/output.mp4"
if [ ! -f "$f" ]; then
#create test video with keyframes every 75 frames
ffmpeg -lavfi "testsrc2=1280x720;sine=440:1:48000" -g 75 -t 32 "$f" -v 24
ffprobe -select_streams v:0 -skip_frame nokey -show_entries frame=pts_time -of default=nw=1:nk=1 "$f" -v 24
fi

# create list of times
echo "0 5
10 15
20 25
" > /tmp/1.txt

inp=()
i=0
c=""
while read -r ss to; do
  if [ "$ss" != "" ]; then
    inp+=("-ss" $ss "-to" $to "-i" "$f")
    c+="[${i}:v][${i}:a]"
    ((i++))
  fi
done < /tmp/1.txt
ffmpeg "${inp[@]}" -lavfi "${c}concat=$i:1:1" -c:v libx264 -preset fast -crf 25 -c:a aac -b:a 128k "$o" -y
mpv --no-config --osd-fractions --osd-level=2 --keep-open "$o"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.