Concatenate TS files with correct timestamps - ffmpeg

I'm trying to merge multiple ts chunk files to one single file, without any loss of quality or reencoding. The files are taken from a live stream, however I'm trying to merge them in a diffrent order and not the order they were streamed.
Example of files:
0000000033.ts
0000000034.ts
0000000039.ts
0000000044.ts
I tried:
cat 0000000033.ts 0000000034.ts 0000000039.ts 0000000044.ts >combined.ts
and
ffmpeg -i "concat:0000000033.ts|concat:0000000034.ts|concat:0000000039.ts|concat:0000000044.ts" -c copy -bsf:a aac_adtstoasc output.mp4
This kinda works, however I instead of beeing 4 seconds long it's around 15. It plays this way:
[first 2 clips]
[5 secs pause]
[39.ts]
[5 secs pause]
[44.ts]
[done]
This happens to both the cat and ffmpeg combined version. So it seems the ts chunks contain timestamps from the stream that are beeing used.
How can I fix that to make it one continous clip?
The chunks here are more of an example, the chunks will be dynamically selected.

If you have a long list of TS files, you can create a playlist, a file containing a list of the TS files in this line format:
file 'seg-37-a.ts'
These commands produce such a file, with the TS files sorted numerically.
delimiterBeforeFileNumber="-"
ls |egrep '[.]ts$' \
|sort "-t$delimiterBeforeFileNumber" -k2,2n \
|sed -r "s/(.*)/file '\1'/" >ts.files.txt
Then the creation of the single file can read the playlist using the -f concat modifier of ffmpeg's -i option.
ffmpeg -f concat -i ts.files.txt -c copy tsw.014.ts.mp4

Haven't checked whether this works with the concat protocol, but you need to generate a new set of timestamps.
ffmpeg -i "concat:0000000033.ts|0000000034.ts|0000000039.ts|0000000044.ts" \
-c copy -bsf:a aac_adtstoasc -fflags +genpts output.mp4

TS files can actually be merged with the Windows 'copy' command. The following will merge every TS in the current folder. Then, once you have a single ts, transmux to mp4 without re-encoding. I confirm the video duration will be correct unlike ffmpeg's concat.
copy /b *.ts all.ts
ffmpeg -i all.ts -c copy all.mp4

In recent versions of ffmpeg, a bit stream filter setts has appeared that allows you to fix timestamps without transcoding. Try it, in my case it helped.
-bsf "setts=PTS-STARTPTS;DTS-STARTDTS"
I am combining a lot of mpeg ts chunks using unix cat, and then transmuxing to an mp4 container
ffmpeg -abort_on empty_output_stream -hide_banner -loglevel repeat+level+error -progress pipe:1 -i pipe:0 -map 0 -c copy -bsf:a aac_adtstoasc -bsf "setts=PTS-STARTPTS;DTS-STARTDTS" -f mp4 -movflags faststart -y out.mp4

Are the examples accurate in file numbers? as 0033.ts and 0034.ts play together but it takes 5 secs to get to 0039.ts and then another 5 to 0044.ts so 0034 + 5 secs = 0039 and + 5 secs = 0044 so are you joining them in their proper order?
Sorry I misread the question but in regards to your problem once you have the 15 sec clip there is a program called flv editor lite from moyea which will take in and convert a .mp4 file to .flv and allow you to cut the excess time out of the file and export it as one file but then you need to reconvert back to .mp4 again

Related

Concatenating/Splicing overlapping video clips with ffmpeg

I'm trying to concatenate multiple short .mp4 video clips from a security camera. The camera records short clips, with a few seconds on either end of a timespan when motion is detected. For example, two minutes of video will often be broken up into four ~35 second clips, with the first/last few seconds of each clip being duplicative of the last/first few seconds of the previous/next clip.
I simply concatenate the clips together using the ffmpeg concat demuxer, as described here: How to concatenate two MP4 files using FFmpeg?, with
(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4
Or else I transcode them into intermediate MPEG-2 transport streams, which I can then concatenate with the file-level concat protocol, as described here: https://trac.ffmpeg.org/wiki/Concatenate#protocol, with
ffmpeg -i "first file.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i "second file.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
But either way, the resulting video (output.mp4) jumps backward in time a few seconds every half-minute or so because of the duplicated frames.
I want to throw out the duplicate frames, and tie the clips together based on timestamps to achieve smooth playback of the concatenated full-length video. I'd strongly prefer to do this on Windows with ffmpeg if possible. Surely this has been done before, right? Are there timestamps in the .mp4 files that I can use to determine how much overlap there is, and then splice at the proper point-in-time? And if so, how do I read them, how do I splice at an exact point in time, and how do I get around the KeyFrames issue if I can splice at the exact point in time?

How do I use FFMPEG with filter_complex to combine/join a full folder of 40+ audio files into one long mp3?

I have a full directory of 40-50 audio files that I am trying to "concat" into one long mp3.
I was able to do this just testing around with 2 files using the command shown below, but I need an easy way to do this with a script that I can make if I have a folder of many files with complicated file names. This is something I'm going to be doing frequently so if I had a script or something I could use quickly that would be most helpful.
ffmpeg -i a.webm -i b.webm -filter_complex "[0:a] [1:a] concat=n=2:v=0:a=1 [a]" -map [a] -c:a mp3 testfull.mp3
The simplest solution is to use the concat demuxer, but all inputs must be the same format and have the same attributes (sample rate, sample format, channel layout).
printf "file '%s'\n" *.webm > input.txt
ffmpeg -f concat -safe 0 -i input.txt -map 0:a output.mp3
-safe 0 is only needed if your input file names contain special characters.

Use FFMPEG to combine different MP4s with srt into one file

So...probably a very basic question for those of you familiar with FFMPEG (I'm really not). I know that you can combine multiple videos into one using FFMPEG, but what about if each video has its own srt file, saved separately in a 'subs' folder and NOT included in the video itself?
Is it possible for FFMPEG to also combine the srt files into a single one (and recalculate the timestamps), and then merge this into the final, combined video? If so, what would the command be?
For example, I have video1.mp4 and video2.mp4. They have corresponding sub1.srt and sub2.srt. When video1.mp4 and video2.mp4 are merged, the timestamps for sub2.srt will, of course, be out of sync now and need to be corrected by adding the duration of video1.mp4 to the individual timestamps (i.e., if video1 is 30 seconds long, and the first subtitle in sub2.srt appears at the 2-second mark, then after the combination, it should now appear at the (30+2)=32-second mark, and so on.
If it helps, all the files are mp4, and have the same dimensions (720p).
While there might be a (complicated) way to concatenate the srt files first, the easiest way is to combine pairs of video and text first, and then concatenate the resulting container files.
Copy everything from video1.mp4 and add subtitles from sub1.srt
# Assuming English for subtitle language
ffmpeg -i video1.mp4 -i sub1.srt -c copy -c:s mov_text -metadata:s:s:0 language=en -metadata:s:s:0 title=English 1.mp4
-c copy will copy everything that might be in video1.mp4, and -c:s mov_text will format the text stream from sub1.srt into subtitles for mp4 (mov_text). The result will be written to 1.mp4.
Repeat the same command for all the other video-subtitles pairs.
Create a text file (f.e. chapters.txt) with the resulting file names
file 1.mp4
file 2.mp4
file 3.mp4
…
Concatenate the resulting container files listed in the text file
ffmpeg -f concat -safe 0 -i chapters.txt -c copy everything.mp4
See ffmpeg's concatenate demuxer
There are other ffmpeg commands that can also deal with different dimensions, mentioned in the docs.
For whatever reason I had to explicitly copy the video, audio, and subtitle streams individually on step 4, otherwise I ended up with silent videos. So my step 4 looked like this:
ffmpeg -f concat -safe 0 -i chapter.txt -c:v copy -c:a copy -c:s copy everything.mp4

Concat multiple video and audio files with ffmpeg

I have an array of audio and video clips, where each audio clip has a 1:1 correlation with it's video clip. The encoding of each video and each audio clip are the same. How can I concat all of the audio clips, and all the video clips, then merge them together to output a video. As of now I only figured out how to merge 1 audio clip with 1 video clip:
$ ffmpeg -i video_1.webm -i audio_1.wav -acodec copy -vcodec copy output.mkv
Update
I just came across mkvmerge would this possibly be a better option?
If all the files are encoded with the same codecs then it's easy to do. First merge the audio and video files as you have already done so each pair of files is contained in one mkv. Then you can concatenate them with the concat demuxer like this:
ffmpeg -f concat -i <(printf "file '%s'\n" ./file1.mkv ./file2.mkv ./file3.mkv) -c copy merged.mkv
or:
ffmpeg -f concat -i <(printf "file '%s'\n" ./*.mkv) -c copy merged.mkv
You could also list one file per line in a text file called mergelist.txt (or whatever you want to call it), i.e.:
file './file1.mkv'
file './file2.mkv'
file './file3.mkv'
Then use that as the input, a la:
ffmpeg -f concat -i mergelist.txt -c copy merged.mkv
This is by far the easiest and fastest way to do what you want since it won't re-encode the files, just line them up one after another.
You can find your answer here in this old question:
Concatenate two mp4 files using ffmpeg
This answer is not restricted to MP4. But it will depend on the file format you wanna concatenate!
Once you have your new VIDEO file and AUDIO file, to merge them together:
ffmpeg -i AUDIO -i VIDEO -acodec copy -vcodec copy OUTPUT

Add multiple audio files to video at specific points using FFMPEG

I am trying to create a video out of a sequence of images and various audio files using FFmpeg. While it is no problem to create a video containing the sequence of images with the following command:
ffmpeg -f image2 -i image%d.jpg video.mpg
I haven't found a way yet to add audio files at specific points to the generated video.
Is it possible to do something like:
ffmpeg -f image2 -i image%d.jpg -i audio1.mp3 AT 10s -i audio2.mp3 AT 15s video.mpg
Any help is much appreciated!
EDIT:
The solution in my case was to use sox as suggested by blahdiblah in the answer below. You first have to create an empty audio file as a starting point like that:
sox -n -r 44100 -c 2 silence.wav trim 0.0 20.0
This generates a 20 sec empty WAV file. After that you can mix the empty file with other audio files.
sox -m silence.wav "|sox sound1.mp3 -p pad 0" "|sox sound2.mp3 -p pad 2" out.wav
The final audio file has a duration of 20 seconds and plays sound1.mp3 right at the beginning and sound2.mp3 after 2 seconds.
To combine the sequence of images with the audio file we can use FFmpeg.
ffmpeg -i video_%05d.png -i out.wav -r 25 out.mp4
See this question on adding a single audio input with some offset. The -itsoffset bug mentioned there is still open, but see users' comments for some cases in which it does work.
If it works in your case, that would be ideal:
ffmpeg -i in%d.jpg -itsoffset 10 -i audio1.mp3 -itsoffset 15 -i audio2.mp3 out.mpg
If not, you should be able to combine all the audio files with sox, overlaying or inserting silence to produce the correct offsets and then use that as input to FFmpeg. Not as convenient, but guaranteed to work.
One approach I can think of is to create your audio file for the whole duration of the video first and then mux the audio with the video file

Resources