4

I am looking also for a Linux solution (in a separate question)

I have two recorded video files with the extension .ts. I need to remove some part of the first, split the second, and then merge the first file with the first (split) part of the second file.

They both have the same characteristics:

Format                                   : MPEG-TS
File size                                : 3.16 GiB
Duration                                 : 1h 39mn
Overall bit rate mode                    : Variable
Overall bit rate                         : 4 527 Kbps

Video
ID                                       : 720 (0x2D0)
Menu ID                                  : 6181 (0x1825)
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L4
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 4 frames
Codec ID                                 : 27
Duration                                 : 1h 39mn
Width                                    : 1 440 pixels
Height                                   : 1 080 pixels
Display aspect ratio                     : 16:9
Frame rate                               : 25.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : MBAFF

They also contain multiple audio tracks and subtitles.

I want to process them without transcoding the files, at least be able to remove the beginning etc.

FFMPEG:

ffmpeg -i source.mts gives:

Input #0, mpegts, from 'source1.mts':
      Duration: 01:40:00.76, start: 2995.511878, bitrate: 4526 kb/s
      Program 6181
        Stream #0:0[0x46](fra,fra): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006)
        Stream #0:1[0x2d0]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 1440x1080 [SAR 4:3 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
        Stream #0:2[0x2da](fra): Audio: aac (HE-AAC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 73 kb/s
        Stream #0:3[0x2db](qaa): Audio: aac (HE-AAC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 67 kb/s
        Stream #0:4[0x2dc](deu): Audio: aac (HE-AAC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 49 kb/s
        Stream #0:5[0x2dd](qad): Audio: aac (HE-AAC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 57 kb/s

I think it is very well doable with ffmpeg, which is also cross-platform, as a command that I found here to remove a part of one file.

ffmpeg -i InputFile -vcodec copy -acodec copy -ss 00:12:34.567 -t 00:34:56.789 OutputFile

works, excepting the fact that the input has four audio tracks and in this way only the first (Stream #0:2[0x2da](fra)) audio is taken. What I want is: either all audio, either the third (Stream #0:3[0x2db](qaa)). How to adjust?

ffmpeg should therefore work to:

1. Cut off the beginning of the first file (remove first 2 minutes out of 1h40 min file)

2. Split a second (1 hour) file in two parts (after 3.05 minutes)

3. Join (append) to the end of the first file the 3.05 min part obtained from splitting the second file.


What I have tried:

Openshot: cannot process without transcoding.

Avidemux (Linux): when trying to save it says "This is not MPEG compatible - You cannot use the Copy codec."

Avidemux in Windows: audio is out of sync.

2
  • All I would add is that given the change in scope of the question[s], I would be wary about leaving your unix.SE question open, as it may be seen as cross-posting, which is frowned on. Its up to you to decide if both need to remain open, and I am making no judgement myself but I suspect others might view it as such.
    – bertieb
    Commented Sep 29, 2015 at 12:56
  • @bertieb - Although common answers may be provided, my U&L question now stands as a different one, as it asks for a general Linux solution, while this one asks for a FFMPEG solution in Windows. - I have indeed created an answer for Linux based on your answer here, and posted here a simplified version of your answer, adding also a possible GUI solution.
    – user162573
    Commented Oct 1, 2015 at 12:27

2 Answers 2

4

How do I split and join files using ffmpeg while retaining all audio tracks?

As you have discovered, a bitstream copy will select only one (audio) track, as per the stream specification documentation:

By default, ffmpeg includes only one stream of each type (video, audio, subtitle) present in the input files and adds them to each output file. It picks the "best" of each based upon the following criteria: for video, it is the stream with the highest resolution, for audio, it is the stream with the most channels, for subtitles, it is the first subtitle stream. In the case where several streams of the same type rate equally, the stream with the lowest index is chosen.

To select all audio tracks:

ffmpeg -i InputFile.ts-c copy -ss 00:12:34.567 -t 00:34:56.789 -map 0:v -map 0:a FirstFile.ts

To select the third audio track:

ffmpeg -i InputFile.ts -c copy -ss 00:12:34.567 -t 00:34:56.789 -map 0:v -map 0:a:2 FirstFile.ts

You can read more about and see other examples of stream selection in the advanced options section of the ffmpeg documentation.

I would also combine -vcodec copy -acodec copy from your original command into -c copy as above for compactness of expression.

Split:

So, combining those with what you want to achieve in the two files in terms of splitting for later re-joining:

ffmpeg -i InputOne.ts -ss 00:02:00.0 -c copy -map 0:v -map 0:a OutputOne.ts
ffmpeg -i InputTwo.ts -c copy -t 00:03:05.0 -map 0:v -map 0:a OutputTwo.ts

will give you:

  • OutputOne.ts, which is everything after the first two minutes of the first input file
  • OutputTwo.ts, which is the first 3 minutes and 5 seconds of the second input file

Join:

ffmpeg supports concatenation of files without re-encoding, described extensively in its concatenation documentation.

Create your listing of files to be joined (eg join.txt):

file '/path/to/files/OutputOne.ts'
file '/path/to/files/OutputTwo.ts'

Then your ffmpeg command can use the concat demuxer:

 ffmpeg -f concat -i join.txt -c copy FinalOutput.ts

Since you are working with mpeg transport streams (.ts), you should be able to use the concat protocol as well:

ffmpeg -i "concat:OutputOne.ts|OutputTwo.ts" -c copy -bsf:a aac_adtstoasc output.mp4

Per the example on the concat page linked above. I'll leave that up to you to experiment with.

13
  • I forgot to include the video -mapping, thanks for the reminder. I have updated the question on how to join (concatenate) video files together as per your edit.
    – bertieb
    Commented Sep 29, 2015 at 13:18
  • 1
    To keep all streams (video, audio, subtitles), replace all -maps with the single: -map 0
    – bertieb
    Commented Sep 29, 2015 at 15:41
  • 1
    If the concatdemuxer also only grabs the 'best' track ( would expect it to work differently, but then this is ffmpeg...), I would include the -map 0 in that step as well.
    – bertieb
    Commented Sep 29, 2015 at 15:49
  • 1
    The positioning of ffmpeg commands is very important. -ss can be used either before or after -i for slightly different methods of achieving the same thing (frame-accurate seeking). You can alternatively use -to if you prefer to specify an end time, rather than a duration (-t).
    – bertieb
    Commented Sep 29, 2015 at 17:29
  • 1
    ffmpeg is available for Windows systems via Zeranoe, yes. I'd rather not get into ffmpeg vs avconv, but see superuser.com/questions/507386/… and stackoverflow.com/questions/9477115/…
    – bertieb
    Commented Sep 29, 2015 at 17:44
4

As a simplified answer based on the main one:

To keep data after a start point (up to the end):

ffmpeg -i INPUT -c copy -ss START_TIME -map 0 OUTPUT

To keep data between two time points:

ffmpeg -i INPUT -c copy -ss START_TIME -to END_TIME -map 0 OUTPUT

To keep data of a certain duration after a certain point:

ffmpeg -i INPUT -c copy -ss START_TIME -t DURATION_TIME -map 0 OUTPUT

To keep data of a certain duration after beginning:

ffmpeg -i INPUT -c copy -t DURATION_TIME -map 0 OUTPUT

To keep data from beginning up to a time point:

ffmpeg -i INPUT -c copy -to TIME_POINT -map 0 OUTPUT

TIME may be a number in seconds, or in hh:mm:ss[.xxx]


To join files, create a file called join.txt with the content

file 'path-to-INPUT1'
file 'path-to-INPUT2'
file...etc

then

 ffmpeg -f concat -i join.txt OUTPUT

Or:

To join mpeg files (including transport files)

 ffmpeg -i "concat:INPUT-1|INPUT-2" -c copy -bsf:a aac_adtstoasc OUTPUT

As a GUI solution, I have tried Avidemux but with bad results. When searching a Linux solution I have found this comment here pointing to Avidemux nightly:

"You can try Avidemux, but not the stable one. You should try the win32 version (yes, for windows) with "Wine". It supports H.264 and you must use the double arrow to find out the keyframes because you can[not] cut everywhere (due to the "long gop" thing...). But, as every software like this, you can do JUST CUTS otherwise it will render (in case of transitions, effects, ectc.). http://avidemux.org/nightly/win32/"

I have tested that in Linux/Wine but it should work in Windows too.

enter image description here

To join files, use File-Open to add first file, and then File-Append for the rest.

To save: File - Save.

You must log in to answer this question.