when webm extracts aac, the duration is inconsistent - google-chrome-extension

When I try to extract aac from webm, there will be inconsistencies in duration. aac is ten minutes less. Different webm videos, the gap is not the same.
webm video is generated by chrome extension chrome.tabCapture.capture
code:
chrome.tabCapture.capture({
video: true,
audio: true,
videoConstraints: {
mandatory: {
minWidth: 1920,
minHeight: 1080,
maxWidth: 1920,
maxHeight: 1080,
maxFrameRate: 30,
minFrameRate: 30,
}
}
})
The above code will return a stream, I will use JS's MediaRecorder method to process this stream, and finally save it as a webm file.
code:
new MediaRecorder(stream, {
audioBitsPerSecond: 128000,
videoBitsPerSecond: 2500000,
mimeType: 'video/webm;codecs=vp9'
})
If you don't know the meaning of the above code, it doesn't matter, I will explain the main information:
width: 1920
height: 1080
FPS: 30
audioBits: 128000
videoBits: 2500000
mimeType: video/webm;codecs=vp9
I tried a lot of methods, like the following:
# 1
ffmpeg -i ./source.webm -y -fflags +genpts -max_muxing_queue_size 99999 -r 15 -crf 30 -filter:v crop=750:560:0:0 ./x.mp4
ffmpeg -i ./x.mp4 -y -vn -acodec libfdk_aac -b:a 200k ./x.aac
# 2
ffmpeg -i ./source.webm -y -vn -acodec libfdk_aac -b:a 200k ./x.aac
# 3
ffmpeg -i ./source.webm -y -vn -acodec libfdk_aac -b:a 200k -map 0 ./x.aac
# 4
ffmpeg -i ./source.webm -y -max_muxing_queue_size 99999 -r 15 -crf 30 -filter:v crop=750:560:0:0 ./x.mp4
ffmpeg -i ./source.webm -y -vn -acodec aac -b:a 200k ./x.aac
# etc.
But without exception, all failed. I have been plagued by this problem for 4 days.
webm file download url: https://drive.google.com/file/d/1m4fC1hU-tXFPOZayrYCs-yteSTxw_TaW/view?usp=sharing

What many conferencing or web recording apps do, is not store silence when audio input is missing or silent (as defined by some volume threshold). WebM and MP4 are time-indexed containers and so the media data has the correct timestamps for playback or editing purposes. .mp3 or .aac don't, so without timestamps, the duration is that of the actual amount of audio recorded and stored. An additional issue is that the duration you see with ffmpeg -i in.aac is an estimate based on the file size and the notional bitrate. For a VBR stream, this estimate can be wrong.
Either store and work with the audio in a container with timestamps, like MP4, MKV..etc
ffmpeg -i ./x.mp4 -y -vn -acodec libfdk_aac -b:a 200k ./x.mp4
or plug in the timestamp gaps with audio silence,
ffmpeg -i ./x.mp4 -y -vn -af aresample=async=1:first_pts=0:min_hard_comp=0.01 -acodec libfdk_aac -b:a 200k ./x.aac
This latter command may still show the wrong estimated duration but an editor, after generating peaks, will show the correct duration.

Related

How do I convert wav into an mxf file with timecode?

I'm looking for a way to convert wav(16bit, 48kHz, LPCM) into an mxf file with timecode.
Since ffmpeg supports mxf, I'm trying, but I don't know the command.
ffmpeg -i ./input.wav [hh:mm:ss.ff, name1] [hh:mm:ss.ff, name2]... ./output.mxf
I'm expecting the above command, but does anyone know?
MXF is a pain
The default MXF muxer requires video.
The -timecode option with MXF requires video.
The mxf_opatom muxer allows just audio, but only mono with 48000 MHz sample rate, so each channel will need to be in its own MXF file.
Workaround 1: Pipe
ffmpeg -i input.wav -ar 48000 -c:a pcm_s16le -timecode 01:02:03:04 -f nut - | ffmpeg -i - -c:a pcm_s16le -f mxf_opatom output.mxf
I'm assuming your audio is mono (you didn't say what it is). If your input is multichannel then output each channel into its own file.
Use 01:02:03:04 for non-drop timecode, and 01:02:03.04 or 01:02:03;04 for drop.
Workaround 2: Dummy/blank video
Just ignore the video.
Non-drop timecode:
ffmpeg -f lavfi -i color=r=25 -i input.wav -timecode 01:02:03:04 -c:a copy -shortest output.mxf
Drop timecode:
ffmpeg -f lavfi -i color=r=30000/1001 -i input.wav -timecode 01:02:03.04 -c:a copy -shortest output.mxf

All audios should be played after combing using ffmpeg. But there is only audio for the first part

This code is combining 3 mp4 files using ffmpeg command. Each file has audio.
After combining, I can listen audio for only first part.
How can I solve this problem?
===========================================================================
ffmpeg -y -i "tmp/titled-0c33a83dc70534c67f66.mp4" -i "tmp/titled-1c2fc9a95e644ab135a3.mp4" -i "tmp/titled-73c3fb1a3ea435cacdd2.mp4" -i "logo/logo.png" -filter_complex "
nullsrc=s=1280x720[bg];
[0:v]setpts=PTS-STARTPTS+0/TB[v0];
[1:v]setpts=PTS-STARTPTS+4.039/TB[v1];
[2:v]setpts=PTS-STARTPTS+8.078/TB[v2];
[bg][v0]overlay=x='if(lte(t,4.039),0,min(0,-w*min(1,max(0,0.98*(t-4.039)^2))))':y=0,trim=duration=13.145[bg];
[bg][v1]overlay=x='if(gte(t,8.078),-w*min(1,max(0,0.98*(t-8.078)^2)),max(0,1280*(1-min(1,max(0,0.69*(atan(8*(t-4.039)^2.7)))))))':y=0[bg];
[bg][v2]overlay=x='max(0,1280*(1-min(1,max(0,0.69*(atan(8*(t-8.078)^2.7))))))':y=0"
-y -vcodec h264 -crf 13 -acodec aac -strict -2 "out.mp4"

Problem with combining a video and an audio stream from USB device

I have two USB devices attached to an RPi, both show up as usual as /dev/video0. Here's some additional info coming from two command line inputs:
Device 1, video only (attached to an RPi4):
ffmpeg -f v4l2 -list_formats all -i /dev/video0 reports
[video4linux2,v4l2 # 0xe5e1c0] Compressed: mjpeg :
Motion-JPEG : 1280x720 640x480 320x240
v4l2-ctl --list-formats-ext reports
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 1280x720
Interval: Stepwise 0.033s - 0.033s with step 0.000s
(30.000-30.000 fps)
Size: Discrete 640x480
Interval: Stepwise 0.033s - 0.033s with step 0.000s
(30.000-30.000 fps)
Size: Discrete 320x240
Interval: Stepwise 0.033s - 0.033s with step 0.000s
(30.000-30.000 fps)
Does work: ffmpeg -f v4l2 -i /dev/video0 -vcodec h264_omx -preset ultrafast -tune zerolatency -g 300 -b:v 1M -mpegts_service_type advanced_codec_digital_hdtv -f mpegts udp://OtherMachine:Port?pkt_size=1316
Device 2, video and audio (attached to an RPi3, but does not work either on the RPi4):
ffmpeg -f v4l2 -list_formats all -i /dev/video0 reports
[video4linux2,v4l2 # 0x2c41210] Compressed: mjpeg :
Motion-JPEG : 1920x1080 1280x720
v4l2-ctl --list-formats-ext reports
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
Size: Discrete 1920x1080
Interval: Discrete 0.033s
(30.000 fps)
Interval: Discrete 0.067s
(15.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.033s
(30.000 fps)
Interval: Discrete 0.067s
(15.000 fps)
After quite some tedious work and way too many hours I got this running:
Video only: ffmpeg -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -preset ultrafast -tune zerolatency -g 300 -f matroska udp://OtherMachine:Port?pkt_size=1316
Does not work at all: ffmpeg -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -preset ultrafast -tune zerolatency -g 300 -f mpegts udp://OtherMachine:Port?pkt_size=1316, on "OtherMachine" I do see that there is an incoming data stream via VLC, but it could not be digested properly.
Audio only: ffmpeg -f alsa -thread_queue_size 1024 -i plughw:1 -c:a mp2 -ac 2 -ar 44100 -preset ultrafast -tune zerolatency -b:a 128K -f mpegts udp://OtherMachine:Port?pkt_size=1316
But this does not work either:
ffmpeg -f v4l2 -input_format mjpeg -i /dev/video0 -f alsa -thread_queue_size
1024 -i plughw:1 -c:v copy -c:a mp2 -ac 2 -ar 44100 -preset ultrafast -tune zerolatency -g 300 -b:a 128K -f mpegts udp://OtherMachine:Port?pkt_size=1316
Could you please provide a hint on how to get these two streams for device 2 working together? Both of them come from the same hardware/device, my guess is that the MJPG video stream is somehow not fully compliant with the mpegts standard (like it is for device 1) since it works with matroska, but not with mpegts. Could that be? What needs to be done in that case?
Another hint, with the same kind of hardware setup I can do this
cvlc -vvv v4l2:///dev/video0 --input-slave=alsa://plughw:1,0 --sout='#transcode{acodec=mpga,ab=128}:std{access=http,mux=asf,dst=:Port}'
So, here my understanding is that video gets passed on unchanged (mjpeg) and audio gets transcoded via vlc's mpga which presumably corresponds to mp2 for ffmpeg. The container format is asf, but I was not able to get that running with ffmpeg for no obvious reason. Anyway, picking up this vlc broadcast stream via http://StreamingMachine:Port on any other machine in my network is working well. But how to achieve that with ffmpeg directly and potentially not as http:// but udp:// or pipe stream?
Alternatively, let me ask this question: Given that I have an incoming mjpeg video stream as well as an incoming mp2 audio stream which kind of container format (ok, it's obviously not mpegts) is the most appropriate one for combined streaming across my LAN or even into a pipe for further processing? Believe me, I tried my very best over a couple of hours to find out how to proceed but with no success. At least to my humble knowledge there is nothing such like a table providing answers to questions of that kind.
I'd be glad to get some insights.
Best

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.

Increasing a file's volume using VLC CLI

My goal is to have a script that takes an audio file and increases its volume by 50%.
I currently use the following AutoHotKey snippet to encode a file to MP3:
run_string := "bash -c ""\""c:\Program Files\VideoLAN\VLC\vlc.exe\"" -I dummy \""" . file_path . "\"" --sout='#transcode{acodec=mp3,vcodec=dummy}:standard{access=file,mux=raw,dst=\""" . file_path . ".mp3\""}' vlc://quit"""
How can I modify this line to not only encode to mp3, but also increase the volume of the file by 50%? I tried setting --volume 150 but it just made the file play, while I don't want to play, I want to have it saved with that volume.
If you have suggestions for other Windows-compatible tools to modify audio that can do this, (along with instructions on how to do this) I'll be happy to hear about them.
I suggest you to use ffmpeg. it is very powerful, cross platform 32 or 64 bit, audio and video converter. Can be downloaded from Zeranoe FFmpeg - Builds
Below sample commands work for audio extracting from video, or audio converter with volume increasing or decreasing support.
Extract audio from video to MP3, or convert audio to MP3 (sample InputFilePath_VideoOrAudio = "e:\video.mp4" or "e:\audio.m4a")
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec libmp3lame -ab 192k -ar 48000 -sn -dn -vn "E:\out.mp3"
Extract audio from video to MP3 and increase volume 150% while extracting add -af "volume=1.5" parameter.
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec libmp3lame -ab 192k -ar 48000 -sn -dn -vn -af "volume=1.5" "E:\out.mp3"
List of audio converter parameters (mp3,ogg,ac3,wma,flac,wav,aiff,m4a....). to change volume level while converting to audio add -af "volume=VolumeValue" parameter.
VolumeValue=0.5 decrease volume %50
VolumeValue=1.5 increase volume %150
VolumeValue=2.0 increase volume %200 and so on.
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec libmp3lame -ab 192k -ar 48000 -sn -dn -vn -af "E:\out.mp3"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec ac3 -ab 192k -ar 48000 -sn -dn -vn "E:\out.ac3"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -f ogg -acodec libvorbis -ab 192k -ar 48000 -sn -dn -vn "E:\out.ogg"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec wmav2 -ab 192k -ar 48000 -sn -dn -vn "E:\out.wma"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec flac -sn -dn -vn "E:\out.flac"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -sn -dn -vn "E:\out.wav"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -f aiff -sn -dn -vn "E:\out.aiff"
e:\ffmpeg\ffmpeg.exe -y -i "InputFilePath_VideoOrAudio" -acodec aac -ab 192k -ar 48000 -sn -dn -vn "E:\out.m4a"
Note 1: some codecs can be experimental in such case you should use -strict experimental or -strict -2 parameters.
Note 2: -ab parameter means audio bit rate. Some devices can not play audio file that bit rate greater than -ab 192k. Use -ab 128k or -ab 192k with -ar 44100 parameters to produce audio file that can be playable most of the mobile devices. -ac 2 parameter means stereo -ac 1 means mono.
to convert specific part of the input file use -ss 00:00:00 and -t parameters. -ss means Start From -t means duration. Important: parameter -ss should placed before the -i parameter, otherwise ffmpeg seeks to -ss position slowly.
Samples: assume that input file duration is 00:20:00 (20 minutes)
using only -ss 00:05:00 means convert input file starting from 5th minute to end of the input file. Duration of the output file will be 15 minutes.
using -ss 00:05:00 with -t 120 or -t 00:02:00 means convert 120 seconds, starting from 5th minute. Duration of the output file will be 120 seconds.
e:\ffmpeg\ffmpeg.exe -y -ss 00:05:00 -i "InputFilePath_VideoOrAudio" -t 120 -acodec libmp3lame -ab 192k -ar 48000 -sn -dn -vn -af "E:\out.mp3"
Note: -y means in advance YES to ffmpeg's yes/no questions such as output file already exist, over write? with -y parameters ffmpeg over writes the output file if it is already exist without asking the user.
-sn disables subtitle, -vn disable video, -dn disable data streams for output file.
If you just want a CLI tool then you could use ffmpeg:
ffmpeg.exe -i test.mp3 -af volume=1.5 loud.mp3
^ ^ ^
input new volume level output name
If you'd like to be able to do it programmatically, looking at your profile I deduced that python should not be a problem :)
So you can use the nice pydub module together with ffmpeg (or avconv which it also supports) for your task.
E.g:
from pydub import AudioSegment
AudioSegment.converter = r"C:\PATH_TO_FFMPEG_DIR\bin\ffmpeg.exe"
sound = AudioSegment.from_mp3("test.mp3") # <- the input file
new = sound.export("loud.mp3", format="mp3", parameters=["-vol", "384"]) # 384 <-> 150% volume
new.flush()
new.close()
The reason for 384 is that the ffmpeg doc states that
-vol volume change audio volume (256=normal)
So 256*1.5 = 384
Tested this on my windows 7 machine just now...
Hope this helps.
The "--volume" option in VLC doesn't actually change the volume of the output video as you would think it would. What you want to do is add the compressor filter and then set the "compressor-makup-gain". Set it to a value from 1-24 depending on how loud you want the video to be. So your command would be something like this:
run_string := "bash -c ""\""c:\Program Files\VideoLAN\VLC\vlc.exe\"" -I dummy \""" . file_path . "\"" --sout='#transcode{acodec=mp3,vcodec=dummy,afilter=compressor}:standard{access=file,mux=raw,dst=\""" . file_path . ".mp3 --compressor-makeup-gain=20\""}' vlc://quit"""
By the way, for anyone who is trying to figure out how to use VLC to increase the volume of the audio in a video file, here's how you can do that:
"C:\Program Files (x86)\VideoLAN\VLC\vlc.exe" yoursourcefile.mp4 :sout=#transcode{acodec=mp3,ab=128,channels=2,samplerate=44100,afilter=compressor}:file{dst=outputfilename.mp4} :sout-all :sout-keep --compressor-makeup-gain=20
Replace "yoursourcefile.mp4" and "outputfilename.mp4" with your own file names. In my experience, VLC crashed about half the time I ran this command, so you may need to try it more than once if it crashes on you.
Run this on a dir to increasing all files volume on that dir, one by one (or else it would eat up all CPU)
FOR %f IN (*) DO (start /wait "" "C:\Program Files
(x86)\VideoLAN\VLC\vlc.exe" %f
:sout=#transcode{acodec=mp3,afilter=compressor}:file{dst=Boost%f}
:sout-all :sout-keep --play-and-exit --compressor-makeup-gain=10)
I believe mp3gain has a command line option for this. You could run this as a separate pass over the generated file:
http://mp3gain.sourceforge.net/

Resources