libav / ffmpeg output optimisation for small file sizes - audio

I am using the following command to take an audio mp3 file and make a video out of it (by using a static jpg picture). My aim is to get a mp3 audio that is as small as possible with still acceptable quality.
frequency="11000"
bitrate="45000"
avconv -loop 1 -i a.jpg -i audio.mp3 -shortest -r 1 -metadata STEREO_MODE=mono -c:v libx264 -ar "$frequency" -b:a "$bitrate" -ac 0 result.mkv
My questions are:
1. how can I achieve that the resulting file is MONO?
2. is it possible to reduce the bitrate furthermore? I would like to use values below 45000, too.
3. My aim is to get control of the parameters that influence the file size most significantly. Presently I know that the frequency is quite important. Are there any other parameters that would help me to get a very small output file with still acceptable quality?
Thanks in advance.

Since you are coding to a compressed audio codec, the frequency doesn't directly affect the file size. However, a frequency of 11 kHz will reduce quality of music.
Instead, I'd suggest
frequency="22050"
bitrate="48000"
ffmpeg -loop 1 -i a.jpg -i audio.mp3 -shortest -r 1 -c:v libx264 -crf 28 \
-ar "$frequency" -b:a "$bitrate" -ac 1 result.mkv
The CRF parameter controls video quality - lower values produce better quality but larger files. You'll get more savings from controlling that than audio bitrate, which is at the lower end anyway.
If your build has libfdk_aac included, you can instead use
frequency="22050"
bitrate="32000"
ffmpeg -loop 1 -i a.jpg -i audio.mp3 -shortest -r 1 -c:v libx264 -crf 28 \
-ar "$frequency" -c:a libfdk_aac -profile:a aac_he_v2 -b:a "$bitrate" -ac 1 result.mkv

Related

How do I use ffmpeg to merge all audio streams (in a video file) into one audio channel?

I am attempting to use ffmpeg for a number of files.
The actual number of audio streams (there is usually one channel per stream) per file isn't known until I'm using ffmpeg.
The desired outcome is to somehow have ffmpeg get the count of audio channel, use the number in the command line to amerge those into one single audio channel.
The goal is to create a preview version of the original video file for use in a simple HTML5 page.
Is this possible in just one call to ffmpeg?
(Also, apologies as some parts of this problem I'm still learning about)
Edit:
Dumas stackoverflow asker here.
Yes, I've been trying multiple combinations of ffmpeg args.
To answer the other question, we have video files that have multiple streams, usually with single channels.
I'll post some cmdline examples shortly.
This cmdline example kind of does what I want; there are 8 streams, and I'm able to combine all audio into one. THe issue is having to know the number before running ffmpeg:
ffmpeg -i EXAMPLE.MOV -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=8[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 OUTPUT.mov
You can use ffprobe to find the number of audio streams and use the output as a variable in your ffmpeg command. Bash example using wc to count the audio streams listed by ffprobe:
ffmpeg -i input.mov -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=$(ffprobe -loglevel error -select_streams a -show_entries stream=codec_type -of csv=p=0 input.mov | wc -l)[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 output.mov
The following command should do the same thing as llogan's answer but doesn't recompress the video track and requires you to identify how many audio tracks should be merged together.
If you want to know how many audio streams are present, try:
ffprobe originalfile.mov 2>&1 | grep 'Stream #'
Once you have identified how many audio streams should be merged, use that number in the amerge=inputs=2 parameter here. This command will merge the streams into one and recompress the audio using aac compression.
ffmpeg -i originalfile.mov -c:v copy -c:a aac -b:a 160k -ac 2 -filter_complex amerge=inputs=2 output.mp4

How to convert High bitrate MP3 to lower rate using FFmpeg

We want to convert 320kbps mp3 file to 128kbps mp3 so currently we are using below ffmpeg command but its not working.
ffmpeg -i input.mp3 -codec:a libmp3lame -qscale:a 5 output.mp3
Result:-the output bitrate same as input mp3.
And we are following the FFmpeg Encoding guideline for that here is the link :- https://trac.ffmpeg.org/wiki/Encode/MP3
so please suggest any solution.
I tried your shown command (tested on Windows / commandline) :
ffmpeg -i input.mp3 -codec:a libmp3lame -qscale:a 5 output.mp3
Result : It works for me. However the -qscale:a 5 makes FFmpeg decide on an average bitrate for you. With one (320k) MP3 file I got it giving a close convert of 134kbps. This is expected since :
lame option Average kbit/s Bitrate range kbit/s ffmpeg option
-V 5 130 120-150 -q:a 5
Solution :
Instead of making the internal mp3 frames hold different bitrates (that vary to acommodate the "current" perceived audio, eg: think "silent" parts using smaller rate of bits/bytes compared to "busy" audio parts), so just set a constant bitrate of 128kbps as you need.
I would just set it to constant 128kbps manually and explicitly with :
ffmpeg -i input.mp3 -codec:a libmp3lame -b:a 128k output.mp3
I use this shellscript in order to not visit this stackoverflow-page over and over again :)
#!/bin/bash
[[ ! -n $1 ]] && {
echo "Usage: mp3convert <input.mp3> <output.mp3> <bitrate:56/96/128/256> <channels> <samplerate>"
exit 0
}
set -x # print next command
ffmpeg -i "$1" -codec:a libmp3lame -b:a "$3"k -ac "$4" -ar $5 "$2"
Make sure your version of FFmpeg has libmp3lame enabled. The selected answer didn't work for me, but this did:
ffmpeg -v debug -i "input.mp3" -c:a libmp3lame \
-b:a 128k -ac 2 -ar 44100 -vn "output.mp3"
-ac 2 - output has 2 (stereo) audio channels
-ar 44100 - sample rate of 44100Hz, which is ideal for high quality music.
Although, in 2022 I wouldn't recommend converting to 128kbps since storage space is much more cheap and abundant nowadays.
I think -b:a 192k strikes the best balance between compression and quality for most people (unless you're an audiophile with $1000 headphones, and even then you'd be better off using FLAC anyways).

Concat 2 videos preserving audio timestamp and add overlay (watermark) in single ffmpeg command

I need to perform multiple actions with ffmpeg, problem is that it seem that for add a watermark and concatenate videos I need to re-encode the video. In three steps it would take ages. So I would like to do everything I need with only one video encoding.
I have a Video #1, it has audio. Also I have a Video #2, with audio too. I would like to concat the #1 and #2 (or play #1 first, and then #2) and then add a watermark in #2 for the rest of the video, preserving audio timestamps.
I have searched a lot o internet, so far I got this:
ffmpeg -i Video1.mp4 -itsoffset 4 -i Video2.mp4 -i watermark.png -filter_complex "overlay=5:5" -codec:v libx264 -crf 21 -bf 2 -flags +cgop -pix_fmt yuv420p -codec:a aac -strict -2 -b:a 384k -r:a 48000 -movflags faststart Out.mp4
The sound from Video #2 disappeared and there's no watermark.
I'm not well-versed in ffmpeg, nor in audio & video terminology, so I apologize for possible horrible misconceptions.
Thanks in advance.
Use
ffmpeg -i Video1.mp4 -i Video2.mp4 -i watermark.png
-filter_complex
"[1][2]overlay=5:5[v2];
[0][0:a][v2][1:a]concat=n=2:v=1:a=1"
-c:v libx264 -crf 21 -c:a aac -b:a 384k -ar 48000 -movflags +faststart Out.mp4
For videos to be joined together, one of the concat methods has to be used. In this case, it's the concat filter. This filter requires that both videos have the same resolution and aspect ratio.
First the watermark is overlaid on the 2nd video, then that result is fed to the concat along with the first video's A/V and 2nd video's A.

Why is there ffmpeg codec noise when encoding test tone?

I used FFmpeg to generate a test clip with color bars and a tone. I also made a special filter to dump out the raw audio data to check it. I was surprised to find that there is significant noise riding on the audio tone after it has gone through the AAC codec. Is this expected? Is there a way to prevent it?
To make the test file I used:
ffmpeg -f lavfi -i "smptehdbars=duration=600:size=1280x720:rate=59.94" -qscale:v 1 -pix_fmt yuv420p smpte_r59_720.mp4
then
ffmpeg -i smpte_r59_720.mp4 -f lavfi -i "sine=frequency=1000:sample_rate=48000:duration=600" -qscale:v 1 -vcodec copy -c:a aac -b:a 192k -shortest -map 0:0 -map 1:0 smpte_r59_720T.mp4
and then
ffmpeg -i smpte_r59_720T.mp4 -y -map 0 -acodec aac -vcodec libx264 -crf 23 -bsf:v h264_mp4toannexb smpte_r59_720T.ts
(Trying to do this all in one step kept failing.)
Other variations on this have varying degrees of noise, sometimes above nominal amplitude and sometimes below.
After finding this problem I pulled a third party test tone .WAV file with 44.1KHz sample rate from the web and checked it. The raw file is clean, but the encoded file I made has noise.
Noise on TS SMPTE bars
Clean audio from MP4

ffmpeg add all audio tracks to video conversion (mkv)

I have a script that takes in input a video file (generally avi or mp4) and converts it to a "lower quality" mkv video optimized for web streaming.
The ffmpeg command I use is this one:
ffmpeg -fflags +genpts -i file:"$input" -sn -codec:v:0 libx264 -force_key_frames expr:gte\(t,n_forced*5\) -vf "scale=trunc(min(max(iw\,ih*dar)\,1280)/2)*2:trunc(ow/dar/2)*2" -pix_fmt yuv420p -preset superfast -crf 23 -b:v 1680000 -maxrate 1680000 -bufsize 3360000 -vsync vfr -profile:v high -level 41 -map_metadata -1 -threads 8 -codec:a:0 libmp3lame -ac 2 -ab 320000 -af "aresample=async=1" -y "$output"
The problem is that this command only includes the first audio track of my video. I have some dual language videos (italian and english) for which I want to include both languages.
Is there a simple ffmpeg command option that automatically includes all audio tracks found in a video?
Add -map 0:a to include all audio streams.

Resources