Converting DTS to AAC with ffmpeg shifts spoken audio to the right - ffmpeg

I am using ffmpeg to convert mkv movies to mp4, like so:
$ ffmpeg -i source.mkv -c:v copy -c:a aac destination.mp4
By doing this, the audio stream gets converted from the original DTS:
Stream #0:1: Audio: dts (DTS), 48000 Hz, 5.1(side), fltp, 1536 kb/s (default)
To AAC:
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 394 kb/s (default)
The resulting file plays just fine, except that the spoken audio (what I am assuming would be sent to the central channel in a 5.1 configuration) sounds clearly shifted to the right, when listening through the MacBook's built-in speakers or my stereo headphones. Note that music and other sound effects appear unaffected, properly balanced. Also note that I have been able to reproduce this behavior with a variety of source files.
Here's ffmpeg's banner:
ffmpeg version 4.0.2 Copyright (c) 2000-2018 the FFmpeg developers
built with Apple LLVM version 9.1.0 (clang-902.0.39.2)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.0.2 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma
libavutil 56. 14.100 / 56. 14.100
libavcodec 58. 18.100 / 58. 18.100
libavformat 58. 12.100 / 58. 12.100
libavdevice 58. 3.100 / 58. 3.100
libavfilter 7. 16.100 / 7. 16.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 1.100 / 5. 1.100
libswresample 3. 1.100 / 3. 1.100
libpostproc 55. 1.100 / 55. 1.100

An FFmpeg commit, aacenc: support extended channel layouts using PCEs, in Nov 2017 added support for many more channel layouts than specified in the MPEG standard for AAC. Unfortunately, it seems it has broken encoding for layouts that worked fine before.
The 3.4 release series is the last before the said commit and should be used for multichannel AAC encoding if you encounter an error with more recent builds.
There is an open bug report at https://trac.ffmpeg.org/ticket/7273. You may post a comment in there to showcase your example.

Related

ffmpeg video to jpg frames poor quality

The quality of JPGs extracted by ffmpeg from an mp4 is much poorer than pause frame from video player (vlc). I am looking for ffmpeg cmd option to improve output quality.
Using following cmd :
/home/tools/bin/ffmpeg -i Merkurtransit_20191111_crf20_8fps_crop.mp4 Merkurtransit_20191111_crf20_8fps_crop_%04d.jpg -hide_banner
The ffmpeg cmd is from instructions found here :
https://www.bugcodemaster.com/article/extract-images-frame-frame-video-file-using-ffmpeg
A comparing screen copy is here:
http://skywatcher.space/download/vlc_player_vs_ffmpeg_bug.png
A few items of note. I created the mp4 myself from high res png (actually originally from 16bit tiff) using ffmpeg :
/home/tools/bin/ffmpeg -framerate 8.0 -i ./AS_P10_RS6_png_reg/Merkurtransit_20191111_%03d.png -vf "crop=760:560:20:40" -pix_fmt yuv420p -crf 20 -r 24 -y ./Video/Merkurtransit_20191111_crf20_8fps_crop.mp4
The crf 20 is pretty high quality, close to 100% and the recovered frame should be close to original. The video player pause frame shows adequate quality. (though I can't say if it is on a key frame or not)
ffmpeg version info:
home/tools/bin/ffmpeg -v
ffmpeg version N-80251-g0c7fa15 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
configuration: --prefix=/home/tools/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/tools/ffmpeg_build/include --extra-ldflags=-L/home/tools/ffmpeg_build/lib --bindir=/home/tools/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree
libavutil 55. 24.100 / 55. 24.100
libavcodec 57. 45.100 / 57. 45.100
libavformat 57. 37.101 / 57. 37.101
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 46.101 / 6. 46.101
libswscale 4. 1.100 / 4. 1.100
libswresample 2. 0.101 / 2. 0.101
libpostproc 54. 0.100 / 54. 0.100
FFmpeg is primarily a video convertor and JPEG output is the result of a MJPEG encoder generating a single image. When no rate control parameters are set, a default bitrate of 200 kbps is selected.
For a better quality output, use
ffmpeg -i in.mp4 -q:v 1 -qmin 1 -qmax 1 out%d.jpg
The quantizer is clamped to exactly 1.

How to compile ffmpeg to get only mp3 and mp4 support

I'm building Electron app and I use ffmpeg to convert m4a or webm files to mp3, and also to merge video only mp4 with m4a audio file to mp4.
I am able to achieve this using [media-autobuild-suite] (https://github.com/jb-alvarado/media-autobuild_suite), using light build option, but the size of static files is arround 20mb and I'would like to shrink it a little bit more. I've compiled ffmpeg and ffprobe with this configuration.
--disable-libaom
--disable-version3
# Full
--disable-chromaprint
--disable-cuda-sdk
--disable-decklink
--disable-frei0r
--disable-libbs2b
--disable-libcaca
--disable-libcdio
--disable-libfdk-aac
--disable-libflite
--disable-libfribidi
--disable-libgme
--disable-libgsm
--disable-libilbc
--disable-libkvazaar
--disable-libmodplug
--disable-libnpp
--disable-libopenh264
--disable-libopenmpt
--disable-librtmp
--disable-librubberband
--disable-libssh
--disable-libtesseract
--disable-libxavs
--disable-libzmq
--disable-libzvbi
--disable-opencl
--disable-opengl
--disable-libvmaf
--disable-libcodec2
--disable-libsrt
--disable-ladspa
--disable-ffplay
#--enable-vapoursynth
#--enable-liblensfun
--disable-libndi_newtek
--enable-demuxer=mp3
--enable-demuxer=mov
--enable-demuxer=opus
--enable-parser=ac3
--enable-parser=mpegaudio
--enable-parser=h264
--enable-parser=opus
--enable-protocol=file
--enable-protocol=pipe
--enable-decoder=mp3
--enable-decoder=mp4
--enable-decoder=opus
--enable-encoder=mp3
--enable-encoder=mp4
--enable-encoder=opus
With this configuration I'm getting ffmpeg static file arround 2mb and ffprobe static file arround 2mb but with this error.
C:\Users\Admin\Desktop\ffmpeg compilations\2mb\local64>ffmpeg -i simple.m4a simple.mp3
ffmpeg version N-93147-g9326117bf6 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 8.2.1 (Rev1, Built by MSYS2 project) 20181214
configuration: .... //here comes configuration as described above
libavutil 56. 26.100 / 56. 26.100
libavcodec 58. 47.102 / 58. 47.102
libavformat 58. 26.101 / 58. 26.101
libavdevice 58. 6.101 / 58. 6.101
libavfilter 7. 48.100 / 7. 48.100
libswscale 5. 4.100 / 5. 4.100
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
Guessed Channel Layout for Input Stream #0.0 : stereo
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'simple.m4a':
Metadata:
major_brand : dash
minor_version : 0
compatible_brands: iso6mp41
creation_time : 2018-10-31T19:47:32.000000Z
Duration: 00:02:38.92, start: 0.000000, bitrate: 127 kb/s
Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, 7 kb/s (default)
Metadata:
creation_time : 2018-10-31T19:47:32.000000Z
handler_name : SoundHandler
[NULL # 0000000000486200] Unable to find a suitable output format for 'simple.mp3'
simple.mp3: Invalid argument
Any ideas what else should I include into this static file?
No need to disable things piecemeal: just use --disable-everything then enable what you need.
Here's an example you can start out with:
./configure
--disable-everything
--disable-network
--disable-autodetect
--enable-small
--enable-decoder=aac*,ac3*,opus,vorbis
--enable-demuxer=mov,m4v,matroska
--enable-muxer=mp3,mp4
--enable-protocol=file
--enable-libshine
--enable-encoder=libshine
--enable-filter=aresample
Final binary size will be around 2-3 MB.
No need to enable any parsers: the selected decoders will automatically select whichever are required.
FFmpeg does not have a native MP3 encoder, so you'll need to use an external library such as libmp3lame or libshine. Since you mentioned Android I assumed you'll want libshine instead of libmp3lame to encode MP3.
Test thoroughly. I probably forgot something.
If you really want to go nuts then use --disable-all instead of --disable-everything and you'll additionally have to manually include the FFmpeg libraries that you want, but that's more work and more headache for not much return.
This will allow you to encode MP3 audio from most M4A and Webm inputs:
ffmpeg -i input.webm output.mp3
And will also let you re-mux MP4/M4V + M4A into MP4:
ffmpeg -i video.m4v -i audio.m4a -map 0:v -map 0:a -c copy output.mp4

Set fake duration on h264 video

I have a script that fetches multiple chunks of a video from one place and streams it as a single video to other place (to Kodi player).
Everything seems to work fine except one thing that bothers me, the player doesn't seem to know how long the video is, therefore the total duration increments as the video plays.
I do know the duration of the video from an xml file that contains a link to all the chunks, but I don't know how to write that in the metadata of the first chunk.
The video codec is h264, but I'm not sure if it is wrapped in some container, like mp4.
Here is the ffmpeg -i output for the first chunk:
ffmpeg version 3.1.5 Copyright (c) 2000-2016 the FFmpeg developers
built with Apple LLVM version 8.0.0 (clang-800.0.38)
configuration: --prefix=/usr/local/Cellar/ffmpeg/3.1.5 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --disable-lzma --enable-vda
libavutil 55. 28.100 / 55. 28.100
libavcodec 57. 48.101 / 57. 48.101
libavformat 57. 41.100 / 57. 41.100
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 47.100 / 6. 47.100
libavresample 3. 0. 0 / 3. 0. 0
libswscale 4. 1.100 / 4. 1.100
libswresample 2. 1.100 / 2. 1.100
libpostproc 54. 0.100 / 54. 0.100
[mpegts # 0x7fc3c6000000] start time for stream 0 is not set in estimate_timings_from_pts
Input #0, mpegts, from '/Users/ibra/Desktop/daTgXic4JOI.ts':
Duration: 00:00:17.56, start: 0.000000, bitrate: 1220 kb/s
Program 1
Stream #0:0[0x102]: Data: timed_id3 (ID3 / 0x20334449)
Stream #0:1[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
Stream #0:2[0x101]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 150 kb/s
And here is a messy screenshot of the file opened in a hex editor:
https://www.evernote.com/l/AWlILw5PcmVEl4fSFitOfS2M8Wzy1WTVSZc
Any suggestions of how to insert the video duration in the metadata of the first chunk?
I cannot download the all the chunks and then concat in a single file because this will take too much time and the streaming must be instantly.
The container format is mpegts. There is no standard way to encode a duration in mpegts (or h.264 for that matter). So whatever you do will be proprietary. You could write it to the ID3 metaadata, but then kodi would need to be modified to handle this.

FFmpeg: NetStream.Play.StreamNotFound on RMTP stream

I want to take snapshots periodically of a RTMP live video stream.
I can see the rtmp video stream using VLC. This is the rtmp url:
rtmp://antena3fms35livefs.fplive.net/antena3fms35live-live/stream-antena3_1
I'm using the following command to capture the snapshots, according to the official FFmpeg site here:
ffmpeg -i rtmp://antena3fms35livefs.fplive.net/antena3fms35live-live/stream-antena3_1 -f image2 -vf fps=fps=1 out%d.png
The command produces the following output:
ffmpeg version N-64667-gd595361 Copyright (c) 2000-2014 the FFmpeg developers
built on Jul 14 2014 22:09:48 with gcc 4.8.3 (GCC)
configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzl
libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amr
enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --ena
libavutil 52. 92.100 / 52. 92.100
libavcodec 55. 69.100 / 55. 69.100
libavformat 55. 47.100 / 55. 47.100
libavdevice 55. 13.102 / 55. 13.102
libavfilter 4. 10.100 / 4. 10.100
libswscale 2. 6.100 / 2. 6.100
libswresample 0. 19.100 / 0. 19.100
libpostproc 52. 3.100 / 52. 3.100
HandShake: client signature does not match!
Closing connection: NetStream.Play.StreamNotFound
rtmp://antena3fms35livefs.fplive.net/antena3fms35live-live/stream-antena3_1: Unknown error occurred
I've tried it with another rmtp streams, but I'm still getting the exact same error.
What could be the problem?
Thank you!
I just tried your command and it worked fine for me. Maybe it is something about your FFMPEG installation? I am using version 2.4 on a Mac (tessus build).
I know other/older versions used "librtmp" for rtmp connections, which required some extra options behind the stream URL. See ffmpeg docs here:
ffmpeg documentation on librtmp
And librtmp docs here:
librtmp documentation
For an unprotected live stream, you may want to try quoting the stream URL and appending " live=1" within the quotes:
ffmpeg -i "rtmp://antena3fms35livefs.fplive.net/antena3fms35live-live/stream-antena3_1 live=1" -f image2 -vf fps=fps=1 out%d.png

Save continuous RTSP stream to 5-10 minute long mp4 files

How can I keep the flow (protocol rtsp, codec h264) in file (container mp4)? That is, on inputting an endless stream (with CCTV camera), and the output files in mp4 format size of 5-10 minutes of recording time.
OS: debian, ubuntu
Software: vlc, ffmpeg (avconv)
Currently this scheme is used:
cvlc rtsp://admin:admin#10.1.1.1:554/ch1-s1 --sout=file/ts:stream.ts
ffmpeg -i stream.ts -vcodec copy -f mp4 stream.mp4
But it can not record video continuously (between restarts vlc loses about 10 seconds of live video).
See this question and answer on Server Fault. In short, switch tools. avconv will do what you want. (ffmpeg has become avconv.)
The feature you are looking for is called segmentation. Your command line would look something like this:
avconv -i rtsp://10.2.2.19/live/ch01_0 -c copy -map 0 -f segment -segment_time 300 -segment_format mp4 "capture-%03d.mp4"
Alexander Garden solution works for ffmpep using the version below. Replace avconv with ffmpeg.
./ffmpeg -i rtsp://10.2.2.19/live/ch01_0 -c copy -map 0 -f segment -segment_time 300 -segment_format mp4 "capture-%03d.mp4"
I'm including this header because of the FFmpeg confusion over versions, the ubuntu schism and rapid development.
ffmpeg version N-80023-gd55568d Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.1)
configuration: --prefix=/home/rhinchley/q10/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/rhinchley/q10/ffmpeg_build/include --extra-ldflags=-L/home/rhinchley/q10/ffmpeg_build/lib --bindir=/home/rhinchley/q10/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree
libavutil 55. 24.100 / 55. 24.100
libavcodec 57. 42.100 / 57. 42.100
libavformat 57. 36.100 / 57. 36.100
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 45.100 / 6. 45.100
libswscale 4. 1.100 / 4. 1.100
libswresample 2. 0.101 / 2. 0.101
libpostproc 54. 0.100 / 54. 0.100
Team work: Split the video source and have two processes alternate recording the time frame. You'll want to test how variable the startup time is, and how variable it is. You might want to set the processes priority to realtime to reduce start time variance. There will be some overlap but that sound like it might be ok for your application from what I infer. Example:
p1: sRRRRRRRRRwwwwwwwwsRRRRRRRRRwwwwwwwwsRRRRRRRRR...
p2: wwwwwwwwwsRRRRRRRRRwwwwwwwwsRRRRRRRRRwwwwwwwww...
time -->
s: startup
R: running
w: wait

Resources