I have a capture card that is handled by a program which I intend to run in a Raspberry Pi 3 (I compiled for it) to stream video locally to a Chromecast. This program is run and spits out video data to stdout in a MPEG-TS container with H.264 and AAC codecs.
I wrote a script which basically segments this to serve a HLS/m3u8 stream:
./HDPVR2-testApp | ffmpeg -i - -c copy -f hls -hls_time 2 -hls_flags +delete_segments -hls_list_size 3 -hls_segment_filename /tmp/stream/file_%v_%03d.ts /tmp/stream/out.m3u8
This works well on almost any video player except for Chrome(cast) refusing to play the stream. CORS is configured correctly.
While debugging using chrome://media-internals the next message appears constantly:
ISO-BMFF container metadata for video frame indicates that the frame is a keyframe, but the video frame contents indicate the opposite.
Investigating this further I came across with the fact that Chrome is more strict on how to play video formats.
By following this answer, extracting the H.264 stream and remuxing to a file solved the problem, making both Chrome and Chromecast happy to play the stream. I tested it by using a pipe (cat fixed-recording.mp4 | ffmpeg -i - ...) just to make sure that wasn't an issue.
Is there a way I can fix the container keyframes with ffmpeg on the fly? I need to run this in a RPi 3 which means I won't be able to re-encode the video and I would rather not write into the disk big files. This is what I tried:
- Use
-movflags empty_moov+default_base_moof+frag_keyframeand a combination of them (from StackOverflow). - Using fragmented MP4 stream instead.
- Extracting the raw streams to two files, but failed because both files need to be written constantly.