FFMPEG: how to wrap h264 stream into FLV container? - ffmpeg

What I want is straightforward: wrap H.264 video stream into a FLV container. However, ffmpeg just decode the input stream and pack raw video stream into FLV. The details are described below:
The input stream is captured from a hardware-encoder video camera, and the FLV will be sent to some video server. Firstly I used following command:
$ ffmpeg -framerate 15 -s 320x240 -i /dev/video1 -f flv "rtmp://some.website.com/receive/path"
However, the resultant stream is suspicious. The watching side don't get any H.264 thing. Then I made a test by writing output to local files.
1: Read raw stream, encode by h264_omx, write to FLV file:
$ ffmpeg -framerate 15 -s 320x240 -i /dev/video0 -codec h264_omx -f flv raw_input_h264_omx.flv
......
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 194017.870905, bitrate: 18432 kb/s
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 320x240, 18432 kb/s, 15 fps, 15 tbr, 1000k tbn, 1000k tbc
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (h264_omx))
......
2: Read H264 stream, write to FLV file:
$ ffmpeg -framerate 15 -s 320x240 -i /dev/video1 -f flv h264_input.flv
......
Input #0, video4linux2,v4l2, from '/dev/video1':
Duration: N/A, start: 194610.307096, bitrate: N/A
Stream #0:0: Video: h264 (Main), yuv420p(progressive), 320x240, 15 fps, 15 tbr, 1000k tbn, 2000k tbc
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> flv1 (flv))
......
Then read the two files correspondingly:
$ ffmpeg -i raw_input_h264_omx.flv
......
Stream #0:0: Video: h264 (High), yuv420p(progressive), 320x240, 200 kb/s, 15 fps, 15 tbr, 1k tbn
$ ffmpeg -i h264_input.flv
......
Stream #0:0: Video: flv1, yuv420p, 320x240, 200 kb/s, 15 fps, 15 tbr, 1k tbn
It is clear when I give a H.264 stream, ffmpeg firstly decodes it, then pack the raw video into FLV. How to avoid that happen, and have the H.264 stream packed directly?
Supplement: I will eventually pushing multiple video streams, so don't ask me to allow ffmpeg's silent decoding, and encode the stream again.

Unless told otherwise, ffmpeg will transcode streams.
Use
ffmpeg -framerate 15 -s 320x240 -i /dev/video1 -c copy -f flv "rtmp://website/receive/path"

Related

ffmpeg convert rtmp audio/video stream to icecast2 audio/video stream

I've been using this command to convert my public rtmp audio/video stream to a local mp3 audio icecast2 stream, but I have been unable to do the same for both video and audio.
[Audio Only] (This works fine)
ffmpeg -re -i rtmp://162.142.xx.xxx:xxx/stream -vn -codec:a libmp3lame -b:a 128k -f mp3 -content_type audio/mpeg icecast://source:password#192.168.1.xxx:80/live
I've tried to re-write in order to support video, but I keep hitting dead ends
[Audio & Video Attempt] (this does not work)
ffmpeg -re -i rtmp://162.142.xx.xxx:xxx/stream -codec:v -f mpeg4 -b:v -f mpeg4 -content_type video/mpeg4 icecast://source:password#192.168.1.xxx:80/live
When I run this command, it gives me the error below asking for a suitable format.
$ ffmpeg -re -i rtmp://162.142.xx.xxx:xxx/stream -codec:v -f mpeg4 -b:v -f mpeg4 -content_type video/mpeg4 icecast://source:password#192.168.1.xxx:80/live
[h264 # 0x5598ffbb8980] co located POCs unavailable
[h264 # 0x5598ffbb8980] mmco: unref short failure
Input #0, flv, from 'rtmp://162.142.xx.xxx:xxx/stream':
Metadata:
|RtmpSampleAccess: true
Server : NGINX RTMP (github.com/sergey-dryabzhinsky/nginx-rtmp-module)
displayWidth : 1280
displayHeight : 720
fps : 48
videokeyframe_frequency: 0
profile :
level :
Duration: 00:00:00.00, start: 28117.779000, bitrate: N/A
Stream #0:0: Audio: aac (LC), 48000 Hz, stereo, fltp, 327 kb/s
Stream #0:1: Video: h264 (High), yuv420p(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 2560 kb/s, 48 fps, 48 tbr, 1k tbn
[NULL # 0x5598ffb8bec0] Unable to find a suitable output format for 'mpeg4'
mpeg4: Invalid argument
I am positive that icecast2 can support video streams, however on the few occasions that I was able to actively stream successfully to it, it only showed an empty video embed.
I've re-written the command for AV multiple times while referencing ffmpeg documentation, however my above attempt seems to be the closest (concept-wise) that I have gotten.
What flags/formatting might I be missing which are causing the stream not to work?

how to extract elementary stream from transport stream

i have .ts file looks like the following
Input #0, mpegts, from 'i.ts':
Duration: 00:00:36.32, start: 28752.398067, bitrate: 57694 kb/s
Program 50
Metadata:
service_name : aaa HD
service_provider:
Stream #0:51[0x1f5]: Video: h264 ([27][0][0][0] / 0x001B), none, 90k tbr, 90k tbn, 180k tbc
Stream #0:52[0x1f6]: Audio: mp3 ([3][0][0][0] / 0x0003), 0 channels, fltp
Program 51
Metadata:
service_name : b Music HD
service_provider:
Stream #0:16[0x1ff]: Video: h264 ([27][0][0][0] / 0x001B), none, 90k tbr, 90k tbn, 180k tbc
Stream #0:17[0x200]: Audio: mp3 ([3][0][0][0] / 0x0003), 0 channels, fltp
Program 52
Metadata:
service_name : c ch HD
service_provider:
Stream #0:14[0x209]: Video: h264 ([27][0][0][0] / 0x001B), none, 90k tbr, 90k tbn, 180k tbc
Stream #0:15[0x20a]: Audio: mp3 ([3][0][0][0] / 0x0003), 0 channels, fltp
Program 1510
Metadata:
service_name : asd
service_provider: xyz
Stream #0:18[0x5e7]: Video: h264 ([27][0][0][0] / 0x001B), none, 90k tbr, 90k tbn, 180k tbc
Stream #0:19[0x5e8]: Audio: mp3 ([3][0][0][0] / 0x0003), 0 channels, fltp
i need to extract one video stream and its audio stream from this file for example related to program 50 i tried
ffmpeg -i i.ts -map 0:51 output.mp4
but i got this error
Stream mapping:
Stream #0:51 -> #0:0 (h264 (native) -> h264 (libx264))
Press [q] to stop, [?] for help
Cannot determine format of input stream 0:51 after EOF
Error marking filters as finished
Conversion failed!
I found a solution here
For mapping the whole programs, the syntax is:
ffmpeg -i i.ts -c:v copy -c:a copy -map 0:p:51 output.mp4
I can't verify that solution is actually working with your .ts file.
I created the following sample, that builds a .ts file with two programs, and then extracts each program to .mp4 file:
ffmpeg -y -r 10 -f lavfi -i testsrc=rate=10:size=160x120 -f lavfi -i sine=frequency=1000 -t 5 -c:v libx264 -c:a aac in1.mp4
ffmpeg -y -r 10 -f lavfi -i mandelbrot=rate=10:size=160x120 -f lavfi -i sine=frequency=300 -t 5 -c:v libx264 -c:a aac in2.mp4
ffmpeg -y -i in1.mp4 -i in2.mp4 -map 0:0 -map 0:1 -map 1:0 -map 1:1 -program title=ProgOne:st=0:st=1 -program title=ProgTwo:st=2:st=3 -c:v copy -c:a copy in.ts
ffmpeg -y -i in.ts -c:v copy -c:a copy -map 0:p:1 output1.mp4
ffmpeg -y -i in.ts -c:v copy -c:a copy -map 0:p:2 output2.mp4
1st command builds video test pattern with high frequency beep (output: in1.mp4).
2nd command builds video Mandelbrot pattern with low frequency beep (output: in2.mp4).
3rd command builds transport stream with two programs (output: in.ts).
4th command extracts first program (output: output1.mp4).
5th command extracts second program (output: output2.mp4).

How to generate an RTMP test stream using ffmpeg command?

I would like to test my streaming infrastructure by generating an RTMP test video with a timestamp. This could look like that screen. The image doesn't matter. I'm after the working stream generated on-the-fly and timestamp only. I intend to use the ffmpeg tool for that purpose. The command could look something like
$ ffmpeg -i image.png \
-vf drawtext="fontfile=/Library/Fonts/Arial.ttf: \
timecode='00\:00\:00\:00': r=1: fontcolor=white: \
fontsize=24: box=1: boxcolor=black#0.5: \
boxborderw=5: x=(w-text_w)/2: y=(h-text_h)/2" \
-f flv rtmp://localhost/live/test
I do run locally a streaming server based on NGINX and its RTMP module.
However, the above command gives me the following error:
Input #0, png_pipe, from 'image.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, rgb24(pc), 768x576 [SAR 7874:7874 DAR 4:3], 25 tbr, 25 tbn, 25 tbc
Stream mapping:
Stream #0:0 -> #0:0 (png (native) -> flv1 (flv))
Press [q] to stop, [?] for help
[Parsed_drawtext_0 # 0x7fb78450ece0] Using non-standard frame rate 1/1
Output #0, flv, to 'rtmp://localhost/live/test':
Metadata:
encoder : Lavf57.71.100
Stream #0:0: Video: flv1 (flv) ([2][0][0][0] / 0x0002), yuv420p, 768x576 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 1k tbn, 25 tbc
Metadata:
encoder : Lavc57.89.100 flv
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
[flv # 0x7fb785812a00] Failed to update header with correct duration.
[flv # 0x7fb785812a00] Failed to update header with correct filesize.
frame= 1 fps=0.0 q=8.6 Lsize= 50kB time=00:00:00.00 bitrate=406016.0kbits/s speed=0.019x
video:49kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.451271%
The streaming server operates as expected. The problem is with the command. Would anyone be able to help me?
ffmpeg has testsrc you can use as a test source input stream:
ffmpeg -r 30 -f lavfi -i testsrc -vf scale=1280:960 -vcodec libx264 -profile:v baseline -pix_fmt yuv420p -f flv rtmp://localhost/live/test
-r, scaling, profile, etc are just an example and can be ommited/played with. The point is using -i testsrc

Frame rate control of a ts file

I have a ts file, which is created by encoding raw yuv data using x264enc and muxing it with mpegtsmux.
And this file contains more than one stream. For example it may contain two video streams, or it may contain two video and one text stream like that.
It is of 25 fps, and 720X576 resolution. I would like to change it's fps to say 10, and all the three streams must present in the new ts file also.
Is there any pipeline for this in gstreamer? or any command in ffmpeg? How can i do this?
I don't think that this is possible in GStreamer. At least is not straightforward. However, it should be possible with ffmpeg as long as all the sequences in the file can be discovered correctly.
From the wiki of ffmpeg, map option (https://trac.ffmpeg.org/wiki/Map):
The "map" command basically means "include this stream into the
immediately following OUTPUT file."
Using map option it is possible to re-encode the video stream that you want and keep untouched the others.
Using input.ts file as an example with 2 different video streams and some audio streams, the way to follow should be the next:
ffmpeg -i input.ts -map 0:0 -map 0:2 -map 0:3 -map 0:4 -map 0:23 -map 0:10 -map 0:14 -c:v:0 mpeg2video -r:v:0 10 -c:v:1 copy -c:a copy outputmini.ts
Note that the video streams are 0:0 and 0:23. The first video stream (mpeg2) is re-encoded to 10 fps whereas the 0:23 video stream (x264) is just copied to the output. Remember that if there is some unknown stream in the .ts file you may need to add -ignore_unknown flag.
As specified in the link from ffmpeg, the output stream order is specified in the command execution in the map option placement order. With -c:v:0 mpeg2video option, we select the first output video stream and re-encoding codec, while the -r:v:0 10 option puts the first video stream frame rate to 10 fps. The other options from the command line copies the input stream to output with the same parameters.
ffmpeg outputs next:
Output #0, mpegts, to 'outputmini.ts':
Metadata:
encoder : Lavf57.41.100
Stream #0:0: Video: mpeg2video (Main), yuv420p, 640x576 [SAR 6:5 DAR 4:3], q=2-31, 200 kb/s, 10 fps, 90k tbn, 10 tbc
Metadata:
encoder : Lavc57.50.100 mpeg2video
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream #0:1(spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, 192 kb/s
Stream #0:2(qaa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, 192 kb/s
Stream #0:3(spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, mono, 96 kb/s (visual impaired)
Stream #0:4: Video: h264 ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 50 fps, 50 tbr, 90k tbn, 90k tbc
Stream #0:5(spa): Audio: eac3 ([6][0][0][0] / 0x0006), 48000 Hz, stereo, 256 kb/s
Stream #0:6(spa): Audio: eac3 ([6][0][0][0] / 0x0006), 48000 Hz, mono, 64 kb/s (visual impaired)
Stream mapping:
Stream #0:0 -> #0:0 (mpeg2video (native) -> mpeg2video (native))
Stream #0:2 -> #0:1 (copy)
Stream #0:3 -> #0:2 (copy)
Stream #0:4 -> #0:3 (copy)
Stream #0:23 -> #0:4 (copy)
Stream #0:10 -> #0:5 (copy)
Stream #0:14 -> #0:6 (copy)
The desired output is achieved.
However, even though I'm not sure this could be done, I would get a glimpse to tsMuxeR appllication (http://www.videohelp.com/software/tsMuxeR). It is a very powerful tool to this kind of tasks.

Increase the bitrate tolerance of ffmpeg for creating screenshots of a movie

I'm getting the error bitrate tolerance too small for bitrate so far no problem. I know that there are several switches to increase that but nothing works.
ffmpeg -y -r 1/30 -b:v 999999k -bt 999999k -maxrate 999999k -i in.flv out%03d.jpg
The source of that commandline is directly from ffmpeg. But that crashes:
ffmpeg version N-44123-g5d55830 Copyright (c) 2000-2012 the FFmpeg developers
built on Sep 2 2012 20:23:29 with gcc 4.7.1 (GCC)
[...]
Input #0, flv, from 'in.flv':
Duration: 00:05:00.13, start: 0.000000, bitrate: 259 kb/s
Stream #0:0: Video: flv1, yuv420p, 320x240, 1k tbr, 1k tbn, 1k tbc
Stream #0:1: Audio: nellymoser, 22050 Hz, mono, s16
[mjpeg # 04356860] bitrate tolerance too small for bitrate
[mjpeg # 04317540] ff_frame_thread_encoder_init failed
Output #0, image2, to 'out%03d.jpg':
Stream #0:0: Video: mjpeg, yuvj420p, 320x240, q=2-31, 200 kb/s, 90k tbn, 0.03 tbc
Stream mapping:
Stream #0:0 -> #0:0 (flv -> mjpeg)
Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Some ideas what I'm doing wrong?

Resources