ffmpeg: HLS to mp4 - ffmpeg

I have one m3u8 file with ts segments. I am trying to convert a part of it to mp4 using the below command.
ffmpeg -i playlist.m3u8 -ss 30 -t 120 -c copy -bsf:a aac_adtstoasc -flags +global_header -y output.mp4
I manually calculated where my segments are located and concatenated those to form output.ts. And then converted that to mp4 using the below commands.
ffmpeg -f concat -safe 0 -i <(for f in ./*.ts; do echo "file '$PWD/$f'"; done) -c copy output.ts
ffmpeg -i output.ts -c copy -bsf:a aac_adtstoasc -flags +global_header -y output.mp4
I found that the second approach is taking far lesser time compared to the first one, an order of 10s of seconds. Someone, please let me know whether the comparison makes any sense and why there is so much difference between the two.

I was using -ss incorrectly for the live stream.
-ss has to be used along side -live_start_index 0 before input file option -i input.m3u8.
For the live streaming from FFMpeg part, one should use -f hls -hls_playlist_type event than -f segment -segment_list_flags live for seek to work on live streaming.
As mentioned in the document for -ss, seek doesn't start exactly at 15th sec. And the duration is also not honoured(< 30secs).
ffmpeg -live_start_index 0 -ss 15 -i playlist.m3u8 -t 00:00:30 -c copy -bsf:a aac_adtstoasc -flags +global_header -y input.mp4
When used without -c copy and with transcoding and -accurate_seek, the duration is fine. But the seek position is the same as the one with -c copy.

Related

How to add a hard code of subs to this filter_complex

ffmpeg -ss 00:11:47.970 -t 3.090 -i "file.mkv" -ss 00:11:46.470 -t 1.500 -i "file" -ss 00:11:51.060 -t 0.960 -i "file.mkv" -an -c:v libvpx -crf 31 -b:v 10000k -y -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[outv][outa];[outv]scale='min(960,iw)':-1[outv];[outv]subtitles='file.srt'[outv]" -map [outv] file_out.webm -map [outa] file.mp3
I have a filter where take three different points in a file concat them together and scale them down this part works
Im looking to see how to add to the filter_complex a sub burn in step rendering the subs from the exact timings usings a file that I specify when I use the above code it doesn't work
The subtitles filter is receiving a concatenated stream. It does not contain the timestamps from the original segments. So the subtitles filter starts from the beginning. I'm assuming this is the problem when you said, "it doesn't work".
The simple method to solve this is to make temporary files then concatenate them.
Output segments
ffmpeg -ss 00:11:47.970 -t 3.090 -copyts -i "file.mkv" -filter_complex "scale='min(960,iw)':-1,subtitles='file.srt',setpts=PTS-STARTPTS;asetpts=PTS-STARTPTS" -crf 31 -b:v 10000k temp1.webm
ffmpeg -ss 00:11:46.470 -t 1.500 -copyts -i "file.mkv" -filter_complex "scale='min(960,iw)':-1,subtitles='file.srt',setpts=PTS-STARTPTS;asetpts=PTS-STARTPTS" -crf 31 -b:v 10000k temp2.webm
ffmpeg -ss 00:11:51.060 -t 0.960 -copyts -i "file.mkv" -filter_complex "scale='min(960,iw)':-1,subtitles='file.srt',setpts=PTS-STARTPTS;asetpts=PTS-STARTPTS" -crf 31 -b:v 10000k temp3.webm
The timestamps are reset when fast seek is used (-ss before -i). -copytswill preserve the timestamps so the subtitles filter knows where to start the subtitles.
Make input.txt:
file 'temp1.webm'
file 'temp2.webm'
file 'temp3.webm'
Concatenate with the concat demuxer:
ffmpeg -f concat -i input.txt -c copy output.webm
-c copy enables stream copy mode so it avoids re-encoding to concatenate.

FFMPEG cannot encode video with high speed change

Hi I am trying to speed up and trim clips with FFMPEG version 4.2.2. Is there a limit to how fast you can speed up a clip? If I try to speed up a clip over a certain then the output file cannot be opened.
I have tried two methods without any luck: 1. using the setPTS filter and 2. inputing the file at a faster frame rate.
1.
ffmpeg -i GH012088.MP4 -y -ss 18 -t 0.48 -an -filter:v "setpts=0.096*PTS" -r 25 output.MP4
2.
ffmpeg -r 312.1875 -i GH012088.MP4 -y -ss 18 -t 0.48 -r 25 -an output.MP4
I am trying to create a clip from the input that starts at 1 second in the original clip, plays at 10.4166 x speed and lasts for 0.48 seconds
What am I doing wrong?
Thanks
Use
ffmpeg -ss 1 -i GH012088.MP4 -y -t 0.48 -an -filter:v "setpts=0.096*PTS" -r 25 output.MP4
The seek has to be on the input side, before frames are retimed. The -t has to be on output side, after frames are retimed.
Does the movie have sound?
If yes, than we have to sync speed up audio and video by combine filter:
ffmpeg -i video.avi -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" -f avi video1.avi

Clip long video segment quickly

Let's say I have a video called Concert.mp4. I want to extract a performance from it quickly with minimal reencoding. I want to do the equivalent of this, but faster:
ffmpeg -i "Concert.mp4" -ss 00:11:45 -to 00:18:15 -preset veryfast -y artist.mp4
This takes 17 seconds, which is way too long for our needs.
Now, it turns out that 11:45 and 18:15 don't fall on iframes, so if you try this you will get a 3 second delay at the beginning before the video shows:
ffmpeg -i "Concert.mp4" -ss 00:11:45 -to 00:18:15 -c copy -y artist.mp4
Running this command, we can see where we need to cut:
ffprobe -read_intervals "11:00%19:00" -v error -skip_frame nokey -show_entries frame=pkt_pts_time -select_streams v -of csv=p=0 "Concert.mp4" > frames.txt
So what we need to do is encode the first 3.708 seconds, copy the middle, and then encode the last 5.912 seconds.
I can get the 3 segments to all look perfect (by themselves) like this:
ffmpeg -ss 698.698 -i "Concert.mp4" -ss 6.302 -t 3.708 -c:v libx264 -c:a copy -c:s copy -y clipbegin.mp4
ffmpeg -ss 708.708 -to 1089.088 -i "Concert.mp4" -c copy -y clipmiddle.mp4
ffmpeg -ss 1089.088 -i "Concert.mp4" -t 5.912 -c:v libx264 -c:a copy -c:s copy -y clipend.mp4
ffmpeg -f concat -i segments.txt -c copy -y artist.mp4
segments.txt of course contains the following:
file 'clipbegin.mkv'
file 'clipmiddle.mkv'
file 'clipend.mkv'
I saw this solution presented here, but no amount of tweaking gets it to work for me:
https://superuser.com/a/1039134/73272
As far as I can tell, this method doesn't work at all. It crashes VLC pretty hard no matter what I try.
The combined video keeps glitching after the 3 seconds, probably because the PTS times are different or something (using some options, I have seen warning messages to this effect). Is there anything I can add to the commands above to get this to work? The only requirement is that the middle command must not re-encode the video, but must do a fast copy.
Thanks in advance.
OK, so the answer was just that the latest VLC seems to be buggy. What I did above plays just fine with a very slight pause at the cut point in ffplay, mplayer and PotPlayer.
Following #Gyan's advice, I set the profile and level to match the original (using -profile:v main -level:v 4) and even the slight pause went away.
ffmpeg -ss 698.698 -i "Concert.mp4" -ss 6.302 -t 3.708 -c:v libx264 -c:a copy -c:s copy -profile:v main -level:v 4 -y clipbegin.mp4
ffmpeg -ss 708.708 -to 1089.088 -i "Concert.mp4" -c copy -y clipmiddle.mp4
ffmpeg -ss 1089.088 -i "Concert.mp4" -t 5.912 -c:v libx264 -c:a copy -c:s copy -profile:v main -level:v 4 -y clipend.mp4
ffmpeg -f concat -i segments.txt -c copy -y artist.mp4

ffmpeg - Concat multiple video files, add audio, set length to videos combined length

I have up until now done this in 2 steps.
Concat video files to outputNoAudio.mp4
Add audio to outputNoAudio.mp4 trimming with -shortest
Now I'm trying to do this in one step using this line
ffmpeg -f concat -safe 0 -i 'vidlist.txt' -i 'music.m4a' -c copy -movflags faststart -y 'test.mp4'
If I use -shortest I end up with an output the length of the shortest video in vidlist.txt. What I'm trying to achieve is the length of all videos combined.
As #Mulvya pointed out. The command works with -shortest. I had the times of my test videos wrong when I started testing. Leaving the answer here for for others trying to do the same.
ffmpeg -f concat -safe 0 -i 'vidlist.txt' -i 'music.m4a' -c copy -movflags faststart -shortest -y 'test.mp4'

How to convert a m3u8 playlist file into a video segment

I've been trying to find out solutions but could not, on how to extract a video segment (say an mp4) from a given m3u8 file, where the video starts from some offset and has a particular duration. Wish someone could help.
I tried this:
ffmpeg -i http://foo.herokuapp.com/input_test.m3u8 -acodec copy -vcodec copy -y -loglevel info -f mp4 myNewVideo.mp4
It generates the video, but now I need it to start from a particular offset and it needs to last a particular duration. I know that the offset might need the -ss flag, but it doesn't seem to be working.
Examples for a capture starting at 30s (-ss) with a duration of 10s (-t).
If the input HLS playlist is of type VOD you can do:
ffmpeg -ss 00:00:30 -i http://foo.herokuapp.com/input_test.m3u8 -t 10 -c copy -bsf:a aac_adtstoasc -flags +global_header -y output.mp4
If the input is a Live stream then:
ffmpeg -i http://foo.herokuapp.com/input_test.m3u8 -ss 00:00:30 -t 10 -c copy -bsf:a aac_adtstoasc -flags +global_header -y output.mp4
The seek is done on the output in the second case (-ss after -i).
You can also add a -re before -i for the live stream if you want to avoid fetching the latest 3 segments at once when you execute the command.

Resources