5

I would like to mute a video for very specific sections.

For example, for a video that is 3 minutes long, i want to mute 5-10 seconds, and 33-36 seconds.

Now,

I know how to apply an audio filter.

ffmpeg -i input.mp4 -af "volume=enable='between(t,5,10)':volume=0, volume=enable='between(t,33,36)':volume=0" output.mp4

But it seems that ffmpeg tries to re-encode the entire video! The video and audio has been completely transcoded.

I only need to mute the specific sections, i would like to keep everything else the same.

Is there a quick way to run it?

Thanks

Zhen Liu
  • 203

2 Answers2

5

What you are missing here is the specification of what codecs you want to use for the transcoding of the audio and video streams.

  • to specify the audio codec, use: -c:a
  • to specify the video codec, use: -c:v

If you want to simply rewrap the data, and not perform any transcoding, you can use "copy" as the video/audio codecs (i.e. "-c:a copy" "-c:v copy").

However, it is not possible to "copy" the video or audio streams when ANY filters are being used on that stream. Think - if you are literally making a "copy" of the 1s and 0s that make up the original audio and video, and creating an output with those same 1s and 0s, you cannot change anything about the data. Filters change the actual bytes that make up the data, so it is not possible to apply a filter and also "copy" the data at the same time.

In your case, you will be forced to transcode the audio stream because you are using an audio filter on that stream. You could however leave the video stream alone by using the "-c:v copy" argument.

For your audio stream, if it is quality you are concerned with, you can specify an uncompressed audio codec using "-c:a pcm_s16le". However, IIRC that codec is not compatible with the MP4 container.

occvtech
  • 1,920
2

To do the least amount of re-encoding in the requested scenario, here are the processes that I've used:

Single command:

ffmpeg -i video.mp4 -filter:a:1 "volume=0:enable='between(t,5,10)+between(t,33,36)'" -c:v copy -c:a:0 copy -c:a:1 aac -map 0:v -map 0:a output.mp4
  • -filter:a:1 applies the filter to the second audio stream
  • between(t,5,10)+between(t,33,36) applies the filter to multiple intervals in the stream
  • -c:v copy copies the video stream without re-encoding
  • -c:a:0 copy copies the first audio stream without re-encoding
  • -c:a:1 aac re-encodes the second audio stream, since that one is having a filter applied to it
  • -map 0:v -map 0:a includes all video and audio streams in the output

Creating ephemeral audio files (left here for posterity, but don't use this approach):

  1. Extract the audio from the video. This does not re-encode the audio.
    ffmpeg -i video.mp4 -vn -acodec copy audio.aac
    
  2. Mute part of the audio. This re-encodes the audio.
    ffmpeg -i audio.aac -af "volume=enable='between(t,5,10)':volume=0" muted-audio.aac
    
  3. Replace the audio stream on the video with the newly muted audio stream that we just created. This does not re-encode the video.
    ffmpeg -i video.mp4 -i muted-audio.aac -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
    
    Source: https://superuser.com/a/277667/379486

The result is that we've only needed to re-encode the audio, which is much less destructive and time consuming than re-encoding the video + audio.