[FFmpeg-user] How do I concat MP4 without losing audio sync?

Mahesh Patade patademahesh at gmail.com
Wed Oct 7 07:57:43 CEST 2015


Hey Peter,

I have written small script to calculate length for each part, split video
into defined number(TOTALPARTS variable in script) of parts and concat
them. I am doing this to achieve Distributed Video Transcoding
<http://patademahesh.github.io/Distributed-Video-Transcoding/>.

#!/bin/bash
FILE="${1}"
FILENAME=$(basename "${FILE}")

# The length of each segment is the total length, divided by the total
number of parts
TOTALPARTS=4

# Determine the duration (length) of the video
TIME=$(mplayer -identify -frames 0 -vo null -nosound "${FILE}" 2>&1 | awk
-F= '/LENGTH/{print $2}')

## First MS
MS=$(echo $TIME |cut -d'.' -f2)
SECONDS=$(echo $TIME |cut -d'.' -f1)

if [ ${MS} -gt 0 ]; then
        MS1=$(echo "0.${MS} * 1000000" | bc)
fi

## Main Seconds
SEC1=$(echo "scale = 3; ${SECONDS} / ${TOTALPARTS}" | bc)

SEC1MS=$(echo ${SEC1} |cut -d'.' -f2)
SEC1SECONDS=$(echo ${SEC1} |cut -d'.' -f1)

if [ ${SEC1MS} -gt 0 ]; then
        SEC1MS1=$(echo "0.${SEC1MS} * 1000000" | bc |cut -d'.' -f1)
fi

MSPERNODE=$(echo "${MS1} / ${TOTALPARTS}" | bc | cut -d'.' -f1)

if [ ! -z ${MSPERNODE} ] && [ ! -z ${SEC1MS1} ]; then
        FINALMICRO=$(echo "${MSPERNODE} + ${SEC1MS1}" | bc)
else
        [ ! -z ${MSPERNODE} ] &&  FINALMICRO=$(echo ${MSPERNODE}|cut -d'.'
-f1)
        [ ! -z ${SEC1MS1} ] &&  FINALMICRO=$(echo ${SEC1MS1}|cut -d'.' -f1)
fi

NODELENGTH="${SEC1SECONDS}.${FINALMICRO}"

LENGTH="$(date -d@${SEC1SECONDS} -u +%H:%M:%S).${FINALMICRO}"

# Convert that HH:MM:SS.xxx to seconds
#SECOND=$(/bin/date -u -d "1970-01-01 ${HHMMSS}" +"%s")

# Calculate each node's start time
if [ ${SEC1SECONDS} -gt 0 ]; then
        TOTALPARTS=$((TOTALPARTS-1))
                a=0
        for i in $(seq 0 $TOTALPARTS); do
                STARTTIME="$(date -d@$(echo "${NODELENGTH} * ${i}" | bc
|cut -d'.' -f1) -u +%H:%M:%S).$(echo "${NODELENGTH} * ${i}" | bc |cut -d'.'
-f2)"
                # Insert into jobs table
                                ffmpeg -ss ${STARTTIME} -t ${LENGTH} -i
"${FILE}" -vcodec libx264 -y "${FILENAME}-${a}.ts"
                                a=$(expr $a + 1)
        done
fi

echo "CONCAT Below files:"
ls -l *.ts

CONCAT=;CONCAT="/dev/null"
for i in $(ls *.ts); do
        if [ -e "${i}" ]; then
                CONCAT="${CONCAT}|${i}"
        fi
done
ffmpeg -i concat:"${CONCAT}" -c copy -bsf:a aac_adtstoasc -y
"${FILENAME}-Concat.mp4"


You need to pass absolute path of the file as argument to script.
*./video_split.sh /root/video.mp4*



Best Regards,
Mahesh Patade


On Tue, Sep 29, 2015 at 9:05 PM, Peter Watkins <peter.watkins at biotronik.com>
wrote:

> I've split and joined MP4 files with QuickTime Player Pro 7 before. I'd
> like to learn how to do the same in FFMPEG. I think I have the syntax
> down, but the audio loses sync in the output MP4. I'm taking a video
> called one_through_ten-timestamped.mp4 splitting it into pieces and
> joining it together again into one_through_ten_edited.mp4. The source
> video was created by FFMPEG using x264.
>
> The problem is that the output video loses audio sync after the join point
> (if played in QuickTime Player X. If played in VLC, the audio and video
> drops out at the join point).
>
> I call FFMPEG on the command-line like this:
>
> ffmpeg -f concat -i ~/Desktop/one_through_ten_edit_list.txt -c copy
> ~/Desktop/one_through_ten_edited.mp4
>
>
> When I run this, I get quite a few errors that look like the following:
>
> [mp4 @ 0x7fdd63863000] Non-monotonous DTS in output stream 0:1; previous:
> 219766, current: 168772; changing to 219767. This may result in incorrect
> timestamps in the output file.
> [concat @ 0x7fdd6300b000] DTS 35840 < 53504 out of order
> [mp4 @ 0x7fdd63863000] Non-monotonous DTS in output stream 0:0; previous:
> 76544, current: 58880; changing to 76545. This may result in incorrect
> timestamps in the output file.
>
> The edit list is as follows:
>
> file one_through_ten-timestamped.mp4
> inpoint 00:00:01.500
> outpoint 00:00:05.000
> file one_through_ten-timestamped.mp4
> inpoint 00:00:09.500
> outpoint 00:00:13.000
>
>
> I understand that I need to split on keyframes--is the problem I'm seeing
> a consequence of splitting on an arbitrary timestamp? If so--how do I
> specify that I only want to split on a keyframe (or determine the
> timestamps for those keyframes)?
>
>
> System:
> OS X 10.9.5
> ffmpeg 2.8 (via MacPorts)
>
> I'd rather not attempt to re-compile the latest GIT snapshot on my Mac if
> I can avoid it. That's why I like MacPorts--I don't have to spend 3 weeks
> determining which patches I need to apply to get something to compile and
> run on my Mac. But if I need to, I'll start working on it.
>
> You may notice this is a cross-post from SuperUser--I didn't get any
> responses there. I probably should have sent an email here first--sorry
> about that.
>
> I've put STDOUT/STDERR on my Google Drive (shared) since it's long. I also
> put the original MP4 and the resulting MP4 there.
>
> STDOUT/STDERR:
>
> https://drive.google.com/file/d/0B01AJq-CMtNMYnlEVGlxRVU4SXc/view?usp=sharing
>
> one_through_ten_edited.mp4
> https://drive.google.com/open?id=0B01AJq-CMtNMYnUyQVVZYTBsS1U
>
> one_through_ten-timestamped.mp4
> https://drive.google.com/open?id=0B01AJq-CMtNMZzJpQTZPQWVuMk0
>
>
> Thanks,
>
> Peter
> _______________________________________________
> ffmpeg-user mailing list
> ffmpeg-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-user
>


More information about the ffmpeg-user mailing list