FFMPEG: Can i set an audio to be played at night only? - audio

This is my working command:
ffmpeg -rtsp_transport tcp -i rtsp://stream1video -i rtsp://stream2audio -re -stream_loop -1 -i 1.aac -re -stream_loop -1 -i 2.aac -filter_complex "[1:a][2:a][3:a]amix=inputs=3[a]" -map 0:v -map "[a]" -c:a aac -f flv rtmp://a.rtmp.youtube.com/
Now, can i somehow set playing the audio streams only at the night? e.g. between 22:00-06:00 each day? And the rest of the day would be just the silence :)
edit: i'm using linux.

Use un cron job (linux/mac) or planified task on windows

Related

Why is adding background music to video using `ffmpeg -i input.mp4 -i music.mp3 output.mp4` not working?

I explored google and StackOverflow for how to add background music to the video and many of them suggested to use
ffmpeg -i input.mp4 -i audio.mp3 -shortest output.mp4
I have been trying to achieve this but it just does not work. When I try to add map like
ffmpeg -i "input.mp4" -i bg.mp3 -map 0:v:0 -map 1:a:0 oo.mp4
The video sound is replaced by the bg.mp3
And if I try -map 0 -map 1:a:0 or not provide map, the audio is not added at all.
How do I add the background music? I don't also get any error.
-map is a selector; select a type of stream from an input "file". To merge two audio streams, you need an audio filter:
ffmpeg -i input.mp4 -i audio.mp3 -lavfi "[0:a][1:a]amerge[out]" -map 0:v -map [out]:a -shortest output.mp4
-lavfi: Same as -filter_complex, because you have two inputs
[0:a][1:a] take audio stream from the first and second inputs
-map 0:v select the video stream from the first input without processing
-map [out]:a select the audio stream from the filtergraph (processed)
The shortest option in the amerge filter is set by default.
If you have problems, you might want to check also the amix filter, the audio codecs of your files, and the volume filter to adjust the volume of the inputs in the filtergraph.
Additional references:
https://ffmpeg.org/ffmpeg-filters.html#amerge
https://ffmpeg.org/ffmpeg-filters.html#amix
https://ffmpeg.org/ffmpeg-filters.html#volume
If the video length is longer than music you can add "-stream_loop -1" to repeat music until end of video
ffmpeg -i video_with_audio.mkv -stream_loop -1 -i background_music.mp3 -lavfi "[0:a][1:a]amerge[out]" -map 0:v -map [out]:a -shortest video_with_audio_and_background_music.mkv
If you want increase or decrease the volume, follow this command:
ffmpeg -i video_with_audio.mkv -stream_loop -1 -i background_music.mp3 -lavfi "[1:a]volume=0.2,apad[A];[0:a][A]amerge[out]" -map 0:v -map [out]:a -shortest video_with_audio_and_background_music.mkv

Optimize ffmpeg overlay and loop filters

I have a video, video.mp4, of 30 seconds, and I have an audio that can change in length, audio.mp3.
My final idea is to have an output video of a loop of video.mp4 for the total length of the audio.mp3, and an overlay of the waveform of the audio.mp3. What I've done is this, in a bash script:
# calculate length of the audio and of the video
tot=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 audio.mp3)
vid=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 video.mp4)
# how many base video we need to loop into the waveform video?
repeattime=`echo "scale=0; ($tot+$vid-1)/$vid" | bc`
# ffmpeg final command
ffmpeg -stream_loop $repeattime -i video.mp4 -i audio.mp3 -filter_complex "[1:a]showwaves=s=1280x100:colors=Red:mode=cline:rate=25:scale=sqrt[outputwave]; [0:v][outputwave] overlay=0:main_h-overlay_h [out]" -map '[out]' -map '1:a' -c:a copy -y output.mp4
Is there a better way to do it in a single ffmpeg command? I know it exists the loop filter in ffmpeg, but it loops frames and I don't know the number of frames of the video.mp4. Also, using $repeattime can result in a number of loop longer then needed (because math calculation is done round up)
-shortest helps you:
#!/bin/bash
ffmpeg -hide_banner -stream_loop -1 -i "input 1.mp4" -i "input 1.mp3" -filter_complex "
[1:a]showwaves=s=1280x100:colors=Red:mode=cline:rate=25:scale=sqrt[outputwave];
[0:v][outputwave] overlay=0:main_h-overlay_h [v]
" -map [v] -map 1:a -c:a copy -shortest -y output.mp4
You can use the shortest option in overlay.
ffmpeg -stream_loop -1 -i video.mp4 -i audio.mp3 -filter_complex "[1:a]showwaves=s=1280x100:colors=Red:mode=cline:rate=25:scale=sqrt[outputwave]; [0:v][outputwave] overlay=0:main_h-overlay_h:shortest=1 [out]" -map '[out]' -map '1:a' -c:a copy -y output.mp4

How to delay audio after a specific position with ffmpeg?

I have a 10 seconds a.mp4 with two streams: Stream #0 is a video stream and Stream #1 is a audio stream.
Now, I want to delay the audio stream by 4 seconds after the time position 00:03. It is to say, in the output file, I want that: 00:00-00:03 is the original audio, 00:03-00:07 has no sound, 00:07-00:14 is the original 00:03-00:10 audio.
I've tried this:
ffmpeg -i a.mp4 -t 00:00:03 -i a.map4 -itsoffset 4 -ss 00:00:03 -i a.mp4 -map 0:v -map 1:a -map 2:a -codec copy output.mp4
But it seems that there are two audio streams in the output.mp4 and only one of them can be played once. Then I tried amix filter:
ffmpeg -i a.mp4 -t 00:00:03 -i a.mp4 -itsoffset 4 -ss 00:00:03 -i a.mp4 -filter_complex "[1:a][2:a] amix=inputs=2" -map 0:v output.mp4
But it also doesn't work. I'm new to ffmpeg so I have no idea what should I do now? Any idea for me? Very much thanks!
Use the asetpts filter to change timestamps, and aresample to (optionally) insert silence in that gap.
ffmpeg -i a.mp4 -af "asetpts='if(lt(T\,3),PTS,PTS+4/TB)',aresample=async=1" -c:v copy output.mp4
Test without aresample to see if your player is tolerant of large gaps in the audio stream.

Singler line FFMPEG cmd to Merge Video /Audio and retain both audios

I have a project that requires merging of a video file with another audio file. The expected out put is an video file that will have both the audio from actual video and the merged audio file. The length of the output video file will be same to the size of the actual video file.
Is there a single line FFMPEG command to achieve this using copy and -map parameters ?
The video form I will be using is either flv or mp4
And the audio file format will be mp3
There can be achieved without using map also.
ffmpeg -i video.mp4 -i audio.mp3 output.mp4
In case you want the output.mp4 to stop as soon as one of the input stops (audio/video)
then use
-shortest
For example: ffmpeg -i video.mp4 -i audio.mp3 -shortest output.mp4
This will make sure that the output stops as and when any one of the inputs is completed.
Since you have asked that you want to do it with map. this is how you do it:
ffmpeg -i video.mp4 -i audio.mp3 -map 0:0 -map 1:0 -shortest output.mp4
Now, since you want to retain the audio of the video file, consider you want to merge audio.mp3 and video.mp4. These are the steps:
Extract audio from the video.mp4
ffmpeg -i video.mp4 1.mp3
Merge both audio.mp3 and 1.mp3
ffmpeg -i audio.mp3 -i 1.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 audiofinal.mp3
Remove the audio from video.mp4 (this step is not required. but just to do it properly)
ffmpeg -i video.mp4 -an videofinal.mp4
Now merge audiofinal.mp3 and videofinal.mp4
ffmpeg -i videofinal.mp4 -i audiofinal.mp3 -shortest final.mp4
note: in the latest version of ffmpeg it will only prompt you to use '-strict -2' in case it does then use this:
ffmpeg -i videofinal.mp4 -i audiofinal.mp3 -shortest -strict -2 final.mp4
hope this helps.
You can not do that using one cmd.
1. Get the audio from video file, the audio file name is a.mp3
ffmpeg.exe -i video.mp4 a.mp3
2. Merge two audio files(audio.mp3+a.mp3=audiofinal.mp3)
ffmpeg.exe -i audio.mp3 -i a.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 audiofinal.mp3
3. Merge video file and audio file(video.mp4+audiofinal.mp3=output.mp4)
ffmpeg.exe -i video.mp4 -i audiofinal.mp3 -map 0:v -map 1:a -c copy -y output.mp4
I don't think extracting the audio from the video is necessary. We can just use -filter_complex amix to merge both audios:
ffmpeg -i videowithaudio.mp4 -i audiotooverlay.mp3 -filter_complex amix -map 0:v -map 0:a -map 1:a -shortest videowithbothaudios.mp4
-filter_complex amix overlays the audio from the first input file on top of audio in the second input file.
-map 0:v video stream of the first input file.
-map 0:a audio stream of the first input file.
-map 1:a audio stream of the second input file.
-shortest the length of the output is the length of the shortest input
Use case:
add music to your background
you rendered a video, but muted some part of it, so you don't want to render it again(coz it's too long), instead you render only audio track(fast) and wanna merge it with original video.
Assuming
you have your video with you speech (or just audio track, whatever)
your music_file is not loud. Otherwise, you will not hear yourself D:
Steps:
1) Extract audio from the video
ffmpeg -i test.mp4 1.mp3
test.mp4 - your file
2) Merge both audio.mp3 and 1.mp3
ffmpeg -i audio.mp3 -i 1.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 audiofinal.mp3
audiofinal.mp3 - audio with music
3) Delete audio from original
ffmpeg -i example.mkv -c copy -an example-nosound.mkv
example-nosound.mkv - your video without audio
4) Merge with proper audio
ffmpeg -i audiofinal.mp3 -i example-nosound.wmv -c:v copy -vcodec copy final.wmv
final.wmv - your perfect video.
This is very easy with FFmpeg:
ffmpeg -i vid.mp4 -i audio.mp3 -codec:a libmp3lame -ar 44100 -ab 64k -ac 1 -q:v 1 -pix_fmt yuv420p -map 0:0 -map 1:0
First remove the sound from video if you are not able to merge video and audio by using this command:
ffmpeg -i video.mp4 -an videofinal.mp4

How to overlay/downmix two audio files using ffmpeg

Can I overlay/downmix two audio mp3 files into one mp3 output file using ffmpeg?
stereo + stereo → stereo
Normal downmix
Use the amix filter:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex amix=inputs=2:duration=longest output.mp3
Or the amerge filter:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex amerge=inputs=2 -ac 2 output.mp3
Downmix each input into specific output channel
Use the amerge and pan filters:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex "amerge=inputs=2,pan=stereo|c0<c0+c1|c1<c2+c3" output.mp3
mono + mono → stereo
Use the join filter:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex join=inputs=2:channel_layout=stereo output.mp3
Or amerge:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex amerge=inputs=2 output.mp3
mono + mono → mono
Use the amix filter:
ffmpeg -i input0.mp3 -i input1.mp3 -filter_complex amix=inputs=2:duration=longest output.mp3
More info and examples
See FFmpeg Wiki: Audio Channels
Check this out:
ffmpeg -y -i ad_sound/whistle.mp3 -i ad_sound/4s.wav -filter_complex "[0:0][1:0] amix=inputs=2:duration=longest" -c:a libmp3lame ad_sound/outputnow.mp3
I think it will help.
The amix filter helps to mix multiple audio inputs into a single output.
If you run the following command:
ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT
This command will mix 3 input audio streams (I used two mp3 files, in the example below) into a single output with the same duration as the first input and a dropout transition time of 3 seconds.
The amix filter accepts the following parameters:
inputs:
The number of inputs. If unspecified, it defaults to 2.
duration:
How to determine the end-of-stream.
longest:
The duration of the longest input. (default)
shortest:
The duration of the shortest input.
first:
The duration of the first input.
dropout_transition:
The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.
For example, I ran the following command in Ubuntu:
FFMPEG version: 3.2.1-1
UBUNTU 16.04.1
ffmpeg -i background.mp3 -i bSound.mp3 -filter_complex amix=inputs=2:duration=first:dropout_transition=0 -codec:a libmp3lame -q:a 0 OUTPUT.mp3
-codec:a libmp3lame -q:a 0 was used to set a variable bit rate. Remember that, you need to install the libmp3lame library, if is necessary. But, it will work even without the -codec:a libmp3lame -q:a 0 part.
Reference: https://ffmpeg.org/ffmpeg-filters.html#amix
For merging two audio files with different volumes and different duration following command will work:
ffmpeg -y -i audio1.mp3 -i audio2.mp3 -filter_complex "[0:0]volume=0.09[a];[1:0]volume=1.8[b];[a][b]amix=inputs=2:duration=longest" -c:a libmp3lame output.mp3
Here duration can be change to longest or to shortest, you can also change the volume levels according to your need.
If you're looking to add background music to some voice use the following command as in the gaps the music will become loud automatically:
ffmpeg -i bgmusic.mp3 -i audio.mp3 -filter_complex "[1:a]asplit=2[sc][mix];[0:a][sc]sidechaincompress=threshold=0.003:ratio=20[bg]; [bg][mix]amerge[final]" -map [final] final.mp3
In this threshold is something whose value will decide how much loud the audio should be, the less the threshold more the audio will be. Ratio gives how much the other audio should be compressed, the more the ratio the more the compression is.
If they are different length, you can use apad to add a silent sound to the shortest one
With Bash
set 'amovie=a.mp3 [gg]; amovie=b.mp3 [hh]; [gg][hh] amerge'
ffmpeg -f lavfi -i "$1" -q 0 c.mp3
Example
You can use the following command arguments:
// Command is here
let commandValue = "-y -i \(recordedAudioPath) -i \(backgroundAudio) -filter_complex [\(0):a][\(1):a]amerge=inputs=\(2)[a] -map [a] -ac \(2) -shortest -preset ultrafast \(outputPath)"
MobileFFmpeg.execute(commandValue)

Resources