I am attempting to use ffmpeg to record an HLS Livestream, described by input.m3u8. input.m3u8 contains a number of different bitrate streams: input_01.m3u8, input_02.m3u8, ...; which contain the actual mpeg-ts segmented video files. Frequently the number and quality of the available streams varies. I am trying to make this an automated process so that my co-workers can use it, but I need ffmpeg to always select the best available stream from the input.m3u8 file. Can anybody point me in the right direction on this?
Currently I use:
ffmpeg -n -i "http://path/input_0x.m3u8" -c copy "%path%\%FileName%
where %path% and %filename% are defined by the batch file calling ffmpeg and I manually look up the best bitrate stream.
Related
I am making a datamoshing program in C++, and I need to find a way to remove one frame from a video (specifically, the p-frame right after a sequence jump) without re-encoding the video. I am currently using h.264 but would like to be able to do this with VP9 and AV1 as well.
I have one way of going about it, but it doesn't work for one frustrating reason (mentioned later). I can turn the original video into two intermediate videos - one with just the i-frame before the sequence jump, and one with the p-frame that was two frames later. I then create a concat.txt file with the following contents:
file video.mkv
file video1.mkv
And run ffmpeg -y -f concat -i concat.txt -c copy output.mp4. This produces the expected output, although is of course not as efficient as I would like since it requires creating intermediate files and reading the .txt file from disk (performance is very important in this project).
But worse yet, I couldn't generate the intermediate videos with ffmpeg, I had to use avidemux. I tried all sorts of variations on ffmpeg -y -ss 00:00:00 -i video.mp4 -t 0.04 -codec copy video.mkv, but that command seems to really bug out with videos of length 1-2 frames - while it works for longer videos no problem. My best guess is that there is some internal checker to ensure the output video is not corrupt (which, unfortunately, is exactly what I want it to be!).
Maybe there's a way to do it this way that gets around that problem, or better yet, a more elegant solution to the problem in the first place.
Thanks!
If you know the PTS or data offset or packet index of the target frame, then you can use the noise bitstream filter. This is codec-agnostic.
ffmpeg -copyts -i input -c copy -enc_time_base -1 -bsf:v:0 noise=drop=eq(pos\,11291) out
This will drop the packet from the first video stream stored at offset 11291 in the input file. See other available variables at http://www.ffmpeg.org/ffmpeg-bitstream-filters.html#noise
I recently asked baout how I could download segments of an online m3u8 file, and someone pointed out that this could be accomplished via ffmpeg:
ffmpeg -i [LINK] -codec copy [OUTPUT FILE] #downloads only audio segments;
ffmpeg -i [LINK] -bsf:a aac_adtstoasc -vcodec copy -c copy -crf 50 [OUTPUT] #downloads audio and video segments
For those who aren't familiar, m3u8 is formatted kinda of like a "playlist", with an m3u8 file pointing to a bunch of smaller "segments" which are pieced together to form the whole of the video. As a result, it's completely possible to halt the above commands partway through their execution and still produce a watchable video (i.e. one that will be interpreted correctly by video editors).
I'm wondering if there's a built-in method with ffmpeg that allows me to grab segments N-M of a given m3u8. If there are methods outside of ffmpeg, feel free to mention them as well. Thanks for the help.
After having looked into it, I can say that this isn't possible via ffmpeg. You could theoretically use the -ss and -t parameters to specify a starting point and duration, but ffmpeg appears to look at every clip up until the specified endpoint, making the download process prohibitively long.
If you want to download only a specific number of segments, you need to look at the m3u8 file, find its associated media list, and download segments from that media list.
Say we have many video records that we want merge with -vcodec copy (or equivalent syntax). Without reencoding, without loss of quality. And few records (minor set), with another codecs, parameters and so on. So we can use ffprobe for file, that represent majority of sources. We get lot of information.
But can we get here commandline hints for ffmpeg, that could be used to convert another (not yet "compatible") files to this same format? At least for one selected stream of "master" file, for example.
Question is not about some scpecific output codec and so on.
There is no exsitsing tool to to this. You would need to write one.
Each video stream inside a video file can only include same codec. So I recommend you to at first step, merge files with same codec with -vcodec copy. The check if which codec is mostly available in your merged files (e.g. CodecA). At second step, convert other merged files with other codecs to CodecA. Finally, merge all files (which all have now CodecA) with -vcodec copy.
Please keep in mind that if the video files are in different sizes, you have to reencode them.
I have 1-5 input streams, each uploading on a slightly different time offset.
With rtmp and ffmpeg, I can reliably encode a single stream into an HLS playlist that plays seamlessly on iOS, my target delivery platform.
I know that you can accept multiple input streams into ffmpeg, and I want to switch between the input streams to create a consistent, single, seamless output.
So I want to switch between
rtmp://localhost/live/stream1 .. rtmp://localhost/live/stream5 on a regular interval. Sometimes there will be multiple streams, and sometimes there won't.
Is there any way for ffmpeg to rotate between input streams while generating an HLS playlist? My goal is to avoid running duplicate instances of ffmpeg for server cost reasons, and I think connecting disparately encoded input streams for playback would be difficult if not impossible.
Switching on each segment is the ideal behavior, but I also need to keep the streams in time sync. Is this possible?
Switching live stream inputs can cause delays due to the initial connection time and buffering (rtmp_buffer).
There's no straight-forward way to do it with ffmpeg. Being an open source project you can add the functionality yourself. It shouldn't be very complicated if all all your inputs share the same codecs, number of tracks, frame sizes etc.
Some people suggested using another software to do the switch such as MLT or using filters such as zmq (ZeroMQ) to make ffmpeg accept commands.
One way to do it would be to re-stream the source as mpgets on a local port and use the local address as input in the command that outputs the HLS:
Stream switcher (60s of each stream, one at a time) - you can make a script with your own logic, this is for illustrative purposes:
ffmpeg -re -i rtmp://.../stream1 -t 60 -f mpegts udp://127.0.0.1:10000
ffmpeg -re -i rtmp://.../stream2 -t 60 -f mpegts udp://127.0.0.1:10000
[...]
ffmpeg -re -i rtmp://.../stream5 -t 60 -f mpegts udp://127.0.0.1:10000
Use the local address as source for the HLS stream - it'll wait for input if there's none and fix your DTS/PTS but you will probably introduce some delays on switching:
ffmpeg -re -i udp://127.0.0.1:10000 /path/to/playlist.m3u8
I'm looking for a MPEG DASH downloader and youtube_dl just hit on me.
Given a .mpd URL, is that possible to use youtube_dl to download all media segments then?
To download all video and audio segments and mux them into a single file, call youtube-dl thus:
youtube-dl -f bestvideo+bestaudio http://URL/TO/manifest.mpd
The option -f <id1>[,<id2>]... is used to select which stream (or streams) of segments to save. The -f bestvideo+bestaudio in this example makes youtube-dl save only the best video and audio streams. See format selection syntax for details and more advanced format selectors. In order to discover the available streams, use youtube-dl -F http://URL/TO/manifest.mpd.
In order to mux (merge) video and audio streams into a single file, you must have FFmpeg or libav installed in your system. Otherwise, youtube-dl will produce a separate file for each stream (in my example, one for audio and one for video).
Without explicit format selection, the default is -f bestvideo+bestaudio/best. Youtube-dl will automatically select the best video and audio, and if there are no separate video-only or audio-only streams, the best stream that contains both video and audio is selected.
youtube-dl http://URL/TO/manifest.mpd
This default is used since version 2015.04.26. Before that (or if -o - is specified, making youtube-dl write output to stdout), the default was -f best, ignoring the video-only and audio-only streams. You may want to specify -f best explicitly when separate video and audio have worse quality than a stream that has both.