Tomin
Tomin

Reputation: 2018

FFMPEG command to mix audio and video with adjustable volume

I have:

I am trying to achieve an output video that has the following qualities:

  1. The volume level of the added audio should be adjustable
  2. The audio should loop till the end of the video
  3. It should not break even if the input video does not have any audio
  4. I should be able to mute the audio of the source video if needed.
  5. All of the above, in the fastest possible way.

I'm not well versed with FFMPEG, maybe some experts could help.

Upvotes: 0

Views: 4652

Answers (1)

Russell Ghana
Russell Ghana

Reputation: 3123

since you are using a library i assume that you know how to run pure FFmpeg commands

based on your third condition we will divide the solution to two part :

It should not break even if the input video does not have any audio

in order to cover this condition, you can check if there is any audio stream in your video file before running any FFmpeg command with below code:

private boolean isVideoContainAudioStream(String videoPath) {
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(videoPath);
    String hasAudioStream = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
    if (hasAudioStream != null && hasAudioStream.equals("yes"))
        return true;
    else
        return false;
}

1. Part One :

so if the result of above function is equal to true, your video file contain audio stream so you can run below command :

ffmpeg -i video.mp4 -filter_complex "amovie=/path/to/audio/file/audio.mp3:loop=0,asetpts=N/SR/TB,volume=2.0[audio];[0:a]volume=0.5[sa];[sa][audio]amix[fa]" -map 0:v -map [fa] -vcodec libx264 -preset ultrafast -shortest fout.mp4

in above command we take audio file at a specific path with amovie filter

  • loop=0, Loop audio infinitely
  • asetpts=N/SR/TB, Generate timestamps by counting samples
  • volume=2.0, multiply audio volume by 2.0

video's audio stream is accessible with [0:a] filter pad so we take it and set the volume to half of the input's volume and name it [sa] obviously if you want to mute the audio of the source video you change that part to :

[0:a]volume=0.0[sa]

after that we will mix two audio streams using amix filter and name it [fa], so far we have everything we wanted, and we just want to merge audio and video streams

  • -vcodec libx264, we are using x264 video encoding because it has lots of configs to gain better performance and speed
  • -shortest, since we loop audio infinitely, we tell the ffmpeg to continue creating frames until the shortest stream ends (video stream is the short one for sure)
  • -preset ultrafast, preset is one of the x264 options, ultrafast will give you more encoding speed at the cost of more size in output file, usually using veryfast value for this flag is a good combination of speed and size

2. Part Two :

if the isVideoContainAudioStream function return false (which means your input video is muted) you can run below command:

ffmpeg -i mute_video.mp4 -filter_complex "amovie=/path/to/audio/file/audio.mp3:loop=0,asetpts=N/SR/TB,volume=2.0[audio]" -map 0:v -map [audio] -vcodec libx264 -preset ultrafast -crf 18 -shortest m_fout.mp4

in above command we use another x264 options called CRF

Constant Rate Factor (CRF)

Use this rate control mode if you want to keep the best quality and care less about the file size. This is the recommended rate control mode for most uses.

The range of the CRF scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible. A lower value generally leads to higher quality, and a subjectively sane range is 17–28. Consider 17 or 18 to be visually lossless or nearly so; it should look the same or nearly the same as the input but it isn't technically lossless.

The range is exponential, so increasing the CRF value +6 results in roughly half the bitrate / file size, while -6 leads to roughly twice the bitrate.

Choose the highest CRF value that still provides an acceptable quality. If the output looks good, then try a higher value. If it looks bad, choose a lower value.

thats it, there is lots of option for x264 encoder, you can check all available options at this link:

H.264 Video Encoding Guide

Upvotes: 4

Related Questions