Not able to pipe gstreamer output into ffmpeg - ffmpeg

has anybody gotten gstreamer to successfully pipe it's video output into ffmpeg?
I've tried playing with /dev/stdout and I keep getting errors:
gst-launch -e v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=1920,height=1080,framerate=5/1' ! nv_omx_h264enc quality-level=2 ! mp4mux ! filesink location=/dev/stdout \
| ffmpeg -y -i - -codec copy -f flv test.flv
...
[aac # 0xebc4c0] Could not find codec parameters for stream 0 (Audio: aac (Main), 7.1, fltp, 1351 kb/s): unspecified sample rate
Consider increasing the value for the 'analyzeduration' and 'probesize' options
pipe:: could not find codec parameters
Input #0, aac, from 'pipe:':
Duration: N/A, bitrate: 1351 kb/s
Stream #0:0: Audio: aac (Main), 7.1, fltp, 1351 kb/s
[flv # 0xec9280] sample rate not set
Output #0, flv, to 'test.flv':
Stream #0:0: Audio: aac, 7.1, 1351 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
ubuntu#tegra-ubuntu:~$
Running the commands separately (replacing /dev/stdout with a file) works fine.
If you got it to work and can share how you did it, that would be great.
Thanks.

You can not use MP4 as a streaming format, as it cannot be parsed linear, e.g. without random access. Therefore it works with files, but not via a pipe.
Replacing the container format with a format that can be streamed should do the trick:
gst-launch -e v4l2src device=/dev/video0 \
! 'video/x-raw-yuv,width=1920,height=1080,framerate=5/1' \
! nv_omx_h264enc quality-level=2 ! matroskamux \
! filesink location=/dev/stdout \
| ffmpeg -y -i - -codec copy -f flv test.flv

Related

Concatenating audio files with ffmpeg results in a wrong total duration

With "wrong total duration" I mean a total duration different from the sum of individual duration of audio files.
sum_duration_files != duration( concatenation of files )
In particular I am concatenating 2 OGG audio files with this command
ffmpeg -safe 0 -loglevel quiet \
-f concat -segment_time_metadata 1 -i {m3u_file_name} \
-vf select=concatdec_select \
-af aselect=concatdec_select,aresample=async=1 \
{ogg_file_name}
And I get the following
# Output of: ffprobe <FILE>.ogg
======== files_in
Input #0, ogg, from 'f1.ogg':
Duration: 00:00:04.32, start: 0.000000, bitrate: 28 kb/s
Stream #0:0: Audio: opus, 48000 Hz, mono, fltp
Input #0, ogg, from 'f2.ogg':
Duration: 00:00:00.70, start: 0.000000, bitrate: 68 kb/s
Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 160 kb/s
Metadata:
ENCODER : Lavc57.107.100 libvorbis
Note durations: 4.32 and 0.7 sec
And this is the output file.
========== files out (concatenate of files_in)
Input #0, ogg, from 'f_concat_v1.ogg':
Duration: 00:00:04.61, start: 0.000000, bitrate: 61 kb/s
Stream #0:0: Audio: vorbis, 48000 Hz, mono, fltp, 80 kb/s
Metadata:
ENCODER : Lavc57.107.100 libvorbis
Duration: 4.61 sec
As 4.61 sec != 4.32 + 0.7 sec I have a problem.
The issue here is using a wrong concatenation approach for these files. As FFmpeg wiki article suggests, file-level concatenation (-f concat) requires all files in the listing to have the exact same codec parameters. In your case, only # of channels (mono) and sample format (flt) are common between them. On the other hand, codec (opus vs. vorbis) and sampling rate (48000 vs. 44100) are different.
-f concat grabs the first set of parameters and runs with it. In your case, it uses 48000 S/s for all the files. Although the second file is 44100 S/s, it assumes 48k (so it'll play it faster than it is). I don't know how the difference in the codec played out in the output.
So, a standard approach is to use -filter_complex concat=a=1:v=1:n=2 with these files given as separate inputs.
Out of curiosity, have you listen to the wrong-duration output file? [edit: never mind, your self-answer indicates one of them is a silent track]
I don't know WHY it happens, but I know how to avoid the problem in my particular case.
My case:
I am mixing (concatenating) different audio files generated by one single source with silence files generated by me.
Initially I generated the silence files with
# x is a float from python
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t {x:2.1f} -q:a 9 -acodec libvorbis silence-{x:2.1f}.ogg
Trying to resolve the issue I re-created those silences with the SAME parameters than the audios I was mixing with, that is (mono at 48Khz):
ffmpeg -f lavfi -i anullsrc=r=48000:cl=mono -t {x:2.1f} -c:a libvorbis silence-{x:2.1f}.ogg
And now ffprobe shows the expected result.
========== files out (concatenate of files_in)
Input #0, ogg, from 'f_concat_v2.ogg':
Duration: 00:00:05.02, start: 0.000000, bitrate: 56 kb/s
Stream #0:0: Audio: vorbis, 48000 Hz, mono, fltp, 80 kb/s
Metadata:
ENCODER : Lavc57.107.100 libvorbis
Duration: 5.02 = 4.32 + 0.70
If you want to avoid problems when concatenating silence with other sounds, do create the silence with the SAME parameters than the sound you will mix with (mono/stereo and Hz)
==== Update 2022-03-08
Using the info provided by #kesh I have recreated the silent ogg files using
ffmpeg -f lavfi -i anullsrc=r=48000:cl=mono -t 5.8 -c:a libopus silence-5.8.ogg
And now the
ffmpeg -safe 0 -f concat -segment_time_metadata 1
-i {m3u_file_name}
-vf select=concatdec_select
-af aselect=concatdec_select,aresample=async=1 {ogg_file_name}
Doesn't throw this error anymore (multiple times).
[opus # 0x558b2c245400] Error parsing the packet header.
Error while decoding stream #0:0: Invalid data found when processing input
I must say that the error was not creating (for me) any problem, because the output was what I expected, but now I feel better without it.

ffmpeg how add header info into pcm?

I use this cmd convert s16le to pcmu8, but will lost header info.
ffmpeg -i s16le.wav -f u8 pcmu8.wav
ffmpeg -i pcmu8.wav
# pcmu8.wav: Invalid data found when processing input
I want known, how add this header info into pcmu8.wav?
It should be this:
ffmpeg -i pcmu8.wav
#Input #0, wav, from 'pcmu8.wav':
# Duration: 00:13:39.20, bitrate: 64 kb/s
# Stream #0:0: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 8000 Hz, mono, u8, 64 kb/s
Your first command is outputting to a raw bitstream, not a WAV, so adding a header won't help. Instead use
ffmpeg -i s16le.wav -c:a pcm_u8 pcmu8.wav

ffmpeg tee muxer failing with error: Tag avc1 incompatible with output codec id '28'

I am able to stream with ffmpeg an mp4 file with h264 encoded video and aac encoded audio to flash flv output. The command I used is:
ffmpeg -re -i bigbuckbunny_HD_60fps.mp4 -c copy -f flv rtmp://192.168.3.64:1935/main/stream0
When I am trying to use the tee option to duplicate the output I am failing with an error. This is the command I use:
ffmpeg -re -i bigbuckbunny_HD_60fps.mp4 -map 0 -c copy -f tee "[f=flv]rtmp://192.168.3.64:1935/main/stream0|[f=flv]rtmp://192.168.3.64:1935/main/stream1"
However, it fails. What I am missing? The output I have from ffmpeg is:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'bigbuckbunny_HD_60fps.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf54.29.104
Duration: 00:10:34.58, start: 0.000000, bitrate: 4279 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 4141 kb/s, 60 fps, 60 tbr, 90k tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
Metadata:
handler_name : SoundHandler
[flv # 0x24607a0] Tag avc1 incompatible with output codec id '28' ([7][0][0][0])
[tee # 0x2365260] Slave '[f=flv]rtmp://192.168.3.64:1935/mainconcept/stream0': error writing header: Invalid data found when processing input
[tee # 0x2365260] Slave muxer #0 failed, aborting.
Could not write header for output file #0 (incorrect codec parameters ?): Invalid data found when processing input
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Last message repeated 1 times
According to ffmpeg -f tee refuses to do anything useful add -tag:v 7 (or -vtag 7, same thing):
ffmpeg -re -i bigbuckbunny_HD_60fps.mp4 -map 0 -c copy -tag:v 7 -f tee "[f=flv]rtmp://192.168.3.64:1935/main/stream0|[f=flv]rtmp://192.168.3.64:1935/main/stream1"
If you get error Tag mp4a incompatible with output codec id '86018' add -tag:a 10 / -atag 10:
ffmpeg -re -i bigbuckbunny_HD_60fps.mp4 -map 0 -c copy -tag:v 7 -tag:a 10 -f tee "[f=flv]rtmp://192.168.3.64:1935/main/stream0|[f=flv]rtmp://192.168.3.64:1935/main/stream1"
Related bug report is #6258: tee muxer fails on stream copy.

ReSample RTP Audio data over Socket as PCM data using FFMPEG

I want to receive a RTP Stream and send the raw data received in it over TCP / UDP socket. For this i am trying following commands.
I am sending the RTP stream using following command.
ffmpeg -re -i hello.wav -ar 8000 -f mulaw -f rtp rtp://127.0.0.1:1234
Receiver to re transmit the stream over TCP / UDP socket.
ffmpeg -i rtp://127.0.0.1:1234 -f mulaw tcp://127.0.0.1:5555 -hide_banner
A Player to play this Socket stream to verify.
ffplay tcp://127.0.0.1:5555?listen
My second command shows that its receiving data and transmitting the data to tcp over 5555 port.
Input #0, rtp, from 'rtp://127.0.0.1:1234':
Duration: N/A, start: 0.000000, bitrate: 64 kb/s
Stream #0:0: Audio: pcm_mulaw, 8000 Hz, mono, s16, 64 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (pcm_mulaw (native) -> pcm_mulaw (native))
Press [q] to stop, [?] for help
Output #0, mulaw, to 'tcp://127.0.0.1:5555':
Metadata:
encoder : Lavf58.29.100
Stream #0:0: Audio: pcm_mulaw, 8000 Hz, mono, s16, 64 kb/s
Metadata:
encoder : Lavc58.54.100 pcm_mulaw
But the third command does not receive anything, even i tried dumping the response into a file using FFMPEG in command three but same results.
What am i doing wrong, Please suggest the correct commands using FFMPEG.
Following three commands worked for me.
ffmpeg -re -i music.wav -ar 8000 -f mulaw -f rtp rtp://127.0.0.1:1236
ffmpeg -i rtp://127.0.0.1:1236 -f wav tcp://127.0.0.1:1256
ffplay tcp://127.0.0.1:1256?listen -ar 8000
I am able to send file as RTP, convert it to raw wav and send it over socket and then play it from that socket.

How do I get audio files of a specific file size?

Is there any way to use ffmpeg to accurately break audio files into smaller files of a specific file size, or pull a specific number of samples from a file?
I'm working with a speech-to-text API that needs audio chunks in exactly 160,000 bytes, or 80,000 16-bit samples.
I have a video stream, and I have an ffmpeg command to extract audio from it:
ffmpeg -i "rtmp://MyFMSWorkspace/ingest/test/mp4:test_1000 live=1" -ar 16000 -f segment -segment_time 10 out%04d.wav
So now I have ~10 second audio chunks with a sample rate of 16 kHz. Is there any way to break this into exactly 160kb, 5 second files using ffmpeg?
I tried this:
ffmpeg -t 00:00:05.00 -i out0000.wav outCropped.wav
But the output was this:
Input #0, wav, from 'out0000.wav':
Metadata:
encoder : Lavf56.40.101
Duration: 00:00:10.00, bitrate: 256 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s
Output #0, wav, to 'outCropped.wav':
Metadata:
ISFT : Lavf56.40.101
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, mono, s16, 256 kb/s
Metadata:
encoder : Lavc56.60.100 pcm_s16le
Stream mapping:
Stream #0:0 -> #0:0 (pcm_s16le (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
size= 156kB time=00:00:05.00 bitrate= 256.1kbits/s
but now the size is 156kb
EDIT:
My finished command is:
ffmpeg -i "url" -map 0:1 -af aresample=16000,asetnsamples=16000 -f segment -segment_time 5 -segment_format sw out%04d.sw
That output looks perfectly right. That ffmpeg size is expressed in KiB although it says kB. 160000 bytes = 156.25 kB + some header data. ffmpeg shows size with fractional part hidden. If you want a raw file, with no headers, output to .raw instead of .wav.
For people converting video files to MP3s split into 30 minute segments:
ffmpeg -i "something.MP4" -q:a 0 -map a -f segment -segment_time 1800 FileNumber%04d.mp3
The -q option can only be used with libmp3lame and corresponds to the LAME -V option (source)

Resources