I want to make a video player that displays more video streams at the same time using the mkv format.
I build my app so that when it decodes an Mkv video it puts all frames from a cluster in memory, from what I observe when I read a video with only one video stream, every cluster except the last one has equal numbers of frames.
I want to merge tow mkv files in one, but at the same time, I want every cluster from the video to have equal numbers of frames from both tracks.
Is this thing possible using FFmpeg or another tool?
Use -frames:v:
ffmpeg -i input0.mkv -i input1.mkv -map 0 -map 1 -c copy -frames:v 100 output.mkv
To verify see Fetch frame count with ffmpeg.
Related
I want to use an ffmpeg command to save segments of length 10 seconds from a video being streamed via HTTP using VLC.
The command I used to carry out the task is:
ffmpeg -i http://[Local IPv4 address]:8080 -f segment -segment_time 10 -vcodec copy -acodec copy -reset_timestamps 1 video%03d.mp4
However, the lengths of the output videos I'm receiving are around 8.333 or 16.666 seconds in duration. (The videos video000.mp4, video005.mp4, video010.mp4, video015.mp4... have duration of around 16.666 seconds and the remaining videos have duration of around 8.333 seconds).
I'm aware that the segmentation of input video happens based on the occurrences of keyframes in the video. It appears that the key frames in the video being streamed occur with an interval of around 8 seconds.
Is there a way to obtain video segments that are closer to 10 seconds in duration from the live stream of such a video?
Also, I occasionally get the "Non-monotonous DTS in output stream 0:0" warning while executing the above command. I tried using different flags (+genpts, +igndts, +ignidx) hoping that the warning message would not be displayed, but no luck. Is it possible that there is any correlation between this warning and the issue with lengths of the segments?
When extracting segments from a media file with video and audio streams without re-encoding (-c copy), it is likely that the requested seek & end time specified will not land precisely on a keyframe in the source.
In this case, ffmpeg will grab the nearest keyframe of each track and position them with differing starting PTS values so that they remain in sync.
Video keyframes tend to be a lot more spaced apart, so you can often end up with something like this:
Viewing the clip in VLC, the audio will start at 5 seconds in.
However, in other video players or video editors I've noticed this can lead to some playback issues or a/v desync.
A solution would be to re-encode both streams when extracting the clip, allowing ffmpeg to precisely seek to the specified seek time and generating equal length & synced audio and video tracks.
However, in my case I do not want to re-encode the video, it is costly and produces lower quality video and/or greater file sizes. I would prefer to only re-encode the audio, filling the initial gap with generated silence.
This should be simple, but everything I've tried has failed to generate silence before the audio stream begins.
I've tried apad, aresample=sync=1, and using amerge to combine the audio with anullsrc. None of it works.
All I can think to possibly get around this is to use ffprobe on the misaligned source to retrieve the first audio PTS, and in a second ffmpeg process apply this value as a negative -itoffset, then concatting the audio track with generated silence lasting the duration of silence... But surely there's a better way, with just one instance of ffmpeg?
Any ideas?
I just stumbled across the solution by trying some more things.
I take the misaligned source media and process it with another ffmpeg instance with some audio filters:
ffmpeg -fflags +genpts -i input.mkv -c copy -c:a aac -af apad,aresample=async=1:first_pts=0 -ac 2 -shortest -y output.mkv
And it does exactly what I want, pads the beginning (and end) of the audio stream with silence making the audio stream equal length to the video.
The only drawback is that I can't combine this with my original ffmpeg command that extracts the clip, the only way this works is as a 2-step process.
I have 30 mkv files which have multiple audio streams and multiple subtitles.
For each file I am trying to: extract the dutch audio and subtitles from that file (25fps)
And merge it with another mkv file (23.976216fps)
With this command it seems like I extract the dutch audio and subtitles into a mkv:
ffmpeg -y -r 23.976216 -i "S01E01 - Example.mkv" -c copy -map 0:m:language:dut S01E01.mkv
But it does not adjust the fps from 25 to 23.976216.
I think I am going to use mkvmerge to merge the two mkv's, but they need to be the same framerate
Anyone knows how I could make this work? Thanks! :)
The frame rate of the video has nothing to do with the frame rate of audio. They are totally independent. In fact there is really no such thing as audio frame rate (well, there is, but that’s a byproduct of the codecs). If you are changing the video frame rate by dropping frames, you are not changing the videos duration, hence you should not change the audios duration. If you are slowing down the video, you must decode the audio, slow it down (likely with pitch correction) and re-encode it.
Something like this would change the audio pitch from standard PAL to NTSC framerate (example valid if your audio track is the 2nd in list, -check with ffmpeg -i video.mkv and see-)
ffmpeg -i video.mkv -vn -map 0:1 -filter:a atempo=0.95904 -y slowed-down-audio-to-23.976-fps.ac3
(23976/25000 = 0.95904 so this is the converted frame rate needed for NTSC films)
Conversely, you can figure out how to speed up NTSC standard frame rate audio to the PAL system (1.0427094).
This trick works, for example, should you want to add a better quality audio track obtained from a different source.
hello everyone I want to split my video into small chunks.I am using ffmpeg segment to achieve this and I want to split the video in same video lenght chunks.I am using ffmpeg segment to split the video.I have written the command
**ffmpeg -i first.mp4 -codec copy -map 0 -f segment -segment_time 10 -segment_list out.list SplitVideo/out%04d.mp4**
When I am executing this command it splits the video in to small chunks but it is not accurate.The chunks are not of same length
From personal experience I realized the following:
Depending on the video format, there are usually dependencies between different frames. It means that some frames are depended on some other frames to be decoded. Therefore the splitting MAYBE cannot be done at any time you want because some of these dependencies might get lost their connections and hence cannot be decoded later. So what ffmpeg does is actually to find the nearest point that is independent from previous frames so all dependencies are satisfied. This will cause different lengths.
I generate a bunch of videos by looping .PNG inputs along with .AMR audio.
ffmpeg -loop 1 -i slide001.png -i slide001.amr -vcodec rawvideo -acodec pcm_s16le -t 5 slide001.avi
Eventually I join the .AVIs using Mencoder. I haven't had much success trying to join them with FFmpeg.
It seems that because the .AMR's actual duration is shorter than the 5 seconds I specified for example, when the time comes to join the .AVIs, the audio stream will be out of sync (ahead of the video).
I suspect I need to find a way of padding the audio with silence or specifying its duration somehow so that the audio and video streams in my .AVIs are of equal length before joining them.
Any ideas?
Thanks.
I ended up solving this by using the SoX audio processor in addition to ffmpeg: http://sox.sourceforge.net/Main/HomePage
The command I use is
sox slide001.wav slide001padded.wav pad 0 3
The above adds 3s of silence to the end of the audio. When ffmpeg's "-t 5" duration command is applied in the video creation, it trims the extra silence so that the video and audio streams are the same length.
This works only when the audio is shorter than the video. You need to add enough silence so that the audio duration equals or exceeds the video duration.