Does ffmpeg supported KLV metadata? - ffmpeg

Is ffmpeg metadata, which is also described in:
http://wiki.multimedia.cx/index.php?title=FFmpeg_Metadata
also supported MISB standard UAV metadata 601.5 ?
Is it same as KLV ?
Thanks,
Ran

FFMPEG does not natively support MISB KLV metadata or have demuxers or decoders for KLV metadata of these types at this time.
However, FFMPEG can be used to extract data elementary streams from containers like MPEG Transport Stream (TS) per ISO 13818-1. Such capability works for UDP streams and local MPEG TS Files. See the examples at end of response. The examples simply extract the data from the stream, they do not parse them. Parsing could easily be accomplished in real time by piping the output or post processing using many languages including C and Python.
It would be helpful to know specifically which containers you are trying to extract data from. In lieu of such information I have assumed MPEG TS in my response and examples. I would like to also point out that the current standard for "UAS Local Dataset" is now ST0601.8 at the time of this response.
I have personally tested the following examples with FFMPEG 2.5.4 on Mac OS X 10.9.5.
The following examples can be modified such that the output is sent to stdout by replacing the <outfile> with '-'.
Extract Data Stream From MPEG-TS File at Line Speed and Save to Binary File:
ffmpeg -i <MPEGTS_infile> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS File at Frame Rate and Save to Binary File:
ffmpeg -re -i <MPEGTS_infile> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS UDP Stream at Stream Rate and Save to Binary File:
ffmpeg -i udp://#<address:port> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS UDP Stream at Stream Rate and Direct to STDOUT:
ffmpeg -i udp://#<address:port> -map d -codec copy -f data -
Stream Video, Audio and Data Streams from MPEG-TS file Over UDP at Frame Rate:
ffmpeg -re -i <MPEGTS_infile> -map 0 -c copy -f mpegts udp://<address:port>

I'm unsure if UAV metadata 601.5 is the same as KLV, but FFmpeg can demux KLV metadata since commit 69a042e from 28 Oct 2013:
mpegts: demux synchronous SMPTE 336M Key-Length-Value (KLV) metadata
This fixes ticket #2579: Data stream from UAV video reported as "Unknown" type and without codec_id set, so you may find other relevant information there too.

Related

Ffmpeg -c copy not carrying over audio track from mkv to hls stream

I am using ffmpeg to create an hls stream. The source is an mkv with multiple audio tracks. I have tried using -map to specify the audio stream as well. I also found that when I point ffmpeg to any other audio stream in the file it works. It's just the first audio stream that does not. At one point I replaced -c copy with -acodec aac -ac 6 on the first stream and I got sound which is great but I am only looking to copy the stream and not re-encode it. The next thing I tried was using other mkv videos I have. All are reflecting the same issue. The mkv's by itself play both audio and video fine in VLC. When playing the output.m3u8 in VLC the option to choose different audio tracks is greyed out. Here is the command I'm using:
ffmpeg -i "./video.mkv" -ss 00:00:00 -t 00:00:30 -c copy -f hls "output.m3u8"
I want the audio of my hls stream to reflect that of the mkv source:
Although what I get returned from the command above gives me no sound and shows me this in mediaInfo:
I've aslo noticed that hls does not support pcm. Is it possible dash could work with this stream because it is pcm?
HLS segments can be either MPEG-TS or fragmented MP4. Neither officially support PCM audio, so you'll have to convert it.
DASH uses fragmented MP4 as segment format.

Re-packetize h264 bytestream to Matroska output

I have an app that's capturing multiple video streams from users and put them into one mkv output file.
Data are from RTP packets. I use h264.
I'm creating mkv using ffmpeg and bytedeco/javacpp-presets bridge for Java.
For some reason my output mkv, after changed container to mp4 (ffmpeg -i input.mkv -c copy output.mp4) is not playable by QuickTime Player. It opens the file but shows nothing but black frame for whole duration.
I'm trying to avoid re-coding of the streams.
One of my attempts to fix this was to somehow pack up raw h264 bytestream and use ffmpeg to put it in mkv again:
ffmpeg -i input.mkv -c copy -f h264 - | ffmpeg -i - -c copy output.mkv
But because raw h264 bytestream has no timing information (ffmpeg warns about lack of timestamps here) it packs it with some constant frame rate which results in different video duration than original. So i.e. from 27min video i get 30min with constant frame rate.
I'm looking for a way to re-pack my h264 video data into mkv container without re-coding.
I also tried NUT container for raw data as it persists some timing informations but result was the same as original mkv - black frame in QuickTime.
Maybe there is some other way to debug why QT shows nothing for my file? Is there any verbosity mode i can enable, some logs to see if it complains for something?
At the datastream level, you need to extract SPS and PPS items from H.264's avcC Coder Configuration Atoms at the beginning of each file and put them into a Matroska SimpleBlock chunk before any other H.264 data.
Or, you can put the avcC data buffer verbatim into your .mkv stream in the header at Segment/Tracks/Track/Codec's private data.
SPS and PPS are standalone NALUs, and Matroska stores them concatenated in byte stream format in the SimpleBlocks.
H.264 video decoders need the data in SPS and PPS to work.

ffmpeg C program to stream ts file through network without changing AV codecs

I am trying to get a sample C source file as example which uses ffmpeg library APIs to stream a ts file as is without changing codec using rtp multicast
./ffmpeg -re -i test_av.ts -acodec copy -vcodec copy -f rtp_mpegts rtp://237.255.5.3:5008
edit:
I am looking for sample C program(s) which could do something close the command I mentioned. I can modify & make required changes if it is somewhat close to what I am trying to achieve. I tried modifying the muxing.c in the doc, however didn't get how to copy codecs & stream through network using rtp multicast.

FFMPEG : Redirecting MP4 muxed data to socket

I am using FFMPEG library to mux H.264 and AAC frames to MP4 file. I can do that both using command line and C program.
Now, instead of writing the muxed MP4 data in to file I want to write these muxed data directly on to socket or pipe. Command line options for that will be appreciated. My actual goal is to write a C program though.
I tried using protocols tcp and udp but they are not working with Mp4 format. They are working with the matroska format.
Following is working.
ffmpeg -i Cartoon.mjpeg -f matroska -r 25 -vcodec copy tcp://10.99.19.224:8888
Following is not and gives error as below.
ffmpeg -i Cartoon.mjpeg -f mp4 -r 25 -vcodec copy tcp://10.99.19.224:8888
Could not write header for output file #0 (incorrect codec parameters ?): Operation not permitted
Any help or advice? Thank you in advance.
Just got one way to output the muxed MP4 output directly on the socket using fragments. I know there are limitations of using fragments but this can be useful.
https://www.ffmpeg.org/ffmpeg-formats.html#Example-1
So following command line is working for me now. I am able to play the MP4 file received from the 8888 port. ffprobe also confirms that its really an MP4 file.
ffmpeg -i Stingray.264 -f mp4 -movflags isml+frag_keyframe -vcodec copy tcp://10.99.19.224:8888
Now I will have to write the C program to do this pragmatically.
If you look at all the ffmpeg output, there is a line:
[mp4 # 0033d660] muxer does not support non seekable output
The mp4 container needs to go back at the beggining of the file to write additional information. A thing that your network socket can not do. So it is not possible to use mp4 container here.

Using FFMPEG to stream continuously videos files to a RTMP server

ffmpeg handles RTMP streaming as input or output, and it's working well.
I want to stream some videos (a dynamic playlist managed by a python script) to a RTMP server, and i'm currently doing something quite simple: streaming my videos one by one with FFMPEG to the RTMP server, however this causes a connection break every time a video end, and the stream is ready to go when the next video begins.
I would like to stream those videos without any connection breaks continuously, then the stream could be correctly viewed.
I use this command to stream my videos one by one to the server
ffmpeg -re -y -i myvideo.mp4 -vcodec libx264 -b:v 600k -r 25 -s 640x360 \
-filter:v yadif -ab 64k -ac 1 -ar 44100 -f flv \
"rtmp://mystreamingserver/app/streamName"
I looked for some workarounds over the internet for many days, and i found some people talking about using a named pipe as input in ffmpeg, I've tried it and it didn't work well since ffmpeg does not only close the RTMP stream when a new video comes but also closes itself.
Is there any way to do this ? (stream a dynamic playlist of videos with ffmpeg to RTMP server without connection breaks
Update (as I can't delete the accepted answer): the proper solution is to implement a custom demuxer, similar to the concat one. There's currently no other clean way. You have to get your hands dirty and code!
Below is an ugly hack. This is a very bad way to do it, just don't!
The solution uses the concat demuxer and assumes all your source media files use the same codec. The example is based on MPEG-TS but the same can be done for RTMP.
Make a playlist file holding a huge list of entry points for you dynamic playlist with the following format:
file 'item_1.ts'
file 'item_2.ts'
file 'item_3.ts'
[...]
file 'item_[ENOUGH_FOR_A_LIFETIME].ts'
These files are just placeholders.
Make a script that keeps track of you current playlist index and creates symbolic links on-the-fly for current_index + 1
ln -s /path/to/what/to/play/next.ts item_1.ts
ln -s /path/to/what/to/play/next.ts item_2.ts
ln -s /path/to/what/to/play/next.ts item_3.ts
[...]
Start playing
ffmpeg -f concat -i playlist.txt -c copy output -f mpegts udp://<ip>:<port>
Get chased and called names by an angry system administrator
Need to create two playlist files and at the end of each file specify a link to another file.
list_1.txt
ffconcat version 1.0
file 'item_1.mp4'
file 'list_2.txt'
list_2.txt
ffconcat version 1.0
file 'item_2.mp4'
file 'list_1.txt'
Now all you need is to dynamically change the contents of the next playlist file.
You can pipe your loop to a buffer, and from this buffer you pipe to your streaming instance.
In shell it would look like:
#!/bin/bash
for i in *.mp4; do
ffmpeg -hide_banner -nostats -i "$i" -c:v mpeg2video \
[proper settings] -f mpegts -
done | mbuffer -q -c -m 20000k | ffmpeg -hide_banner \
-nostats -re -fflags +igndts \
-thread_queue_size 512 -i pipe:0 -fflags +genpts \
[proper codec setting] -f flv rtmp://127.0.0.1/live/stream
Of course you can use any kind of loop, also looping through a playlist.
I figure out that mpeg is a bit more stabile, then x264 for the input stream.
I don't know why, but minimum 2 threads for the mpeg compression works better.
the input compression need to be faster then the output frame rate, so we get fast enough new input.
Because of the non-continuing timestamp we have to skip them and generate a new one in the output.
The buffer size needs to be big enough for the loop to have enough time to get the new clip.
Here is a Rust based solution, which uses this technique: ffplayout
This uses a JSON playlist format. The Playlist is dynamic, in that way that you can edit always the current playlist and change tracks or add new ones.
Very Late Answer, but I recently ran into the exact same issue as the poster above.
I solved this problem by using OBS and the OBS websockets plugin.
First, set your RTMP streaming app as you have it now. but stream to a LOCAL RTMP stream.
Then have OBS load this RTMP stream as a VLC source layer with the local RTMP as the source.
then (in your app), using the OBS websockets plugin, have your VLC source switch to a static black video or PNG file when the video ends. Then switch back to the RTMP stream once the next video starts. This will prevent the RTMP stream from stopping when the video ends. OBS will go black durring the short transition, but the final OBS RTMP output will never stop.
There is surely a way to do this with manually setting up a intermediate RTMP server that pushes to a final RTMP server, but I find using OBS to be easier, with little overhead.
I hope this helps others, this solutions has been working incredible for me.

Resources