32

I'm trying to figure out if a video has audio present in it so as to extract the mp3 using ffmpeg. When the video contains no audio channels, ffmpeg creates an empty mp3 file which I'm using to figure out if audio was present in the video in the first place. I'm sure there is a better way to identify if audio is present in a video. Will avprobe help with this? Can anyone point me to a resource or probably a solution?

Edit: Surprisingly, the same command on my server running the latest build of ffprobe doesn't run. It throws an error saying

Unrecognized option 'select_stream'

Failed to set value 'a' for option 'select_stream'

Any ideas how to rectify this out?

Kartos
  • 749
  • 1
  • 7
  • 18
  • 1
    (Years later): If anyone else has the same error that was added on the edit, check your command. It says "select_stream". It should be "select_stream**s**" – Alfro Nov 10 '17 at 13:05

5 Answers5

38

I would use FFprobe (it comes along with FFMPEG):

ffprobe -i INPUT -show_streams -select_streams a -loglevel error

In case there's no audio it ouputs nothing. If there is an audio stream then you get something like:

[STREAM]

index=0

codec_name=mp3

codec_long_name=MP3 (MPEG audio layer 3)

profile=unknown

codec_type=audio

codec_time_base=1/44100

etc

etc...

[/STREAM]

That should be easy enough to parse regardless of the language you're using to make this process automated.

Community
  • 1
  • 1
AJ29
  • 1,381
  • 10
  • 10
8

If it is normal video file from the local path, you can do something like this to find whether video has audio file or not.

You need to look into the MediaMetadataRetriever

By using METADATA_KEY_HAS_AUDIO you can check whether the video has the audio or not.

private boolean isVideoHaveAudioTrack(String path) {
        boolean audioTrack =false;

        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(path);
        String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
        if(hasAudioStr.equals("yes")){ 
         audioTrack=true; } 
        else{ 
        audioTrack=false; }

        return audioTrack;
    }

Here path is your video file path.

PS: Since it is old question , i am writing this answer to help some other folks , to whom it may help.

King of Masses
  • 18,405
  • 4
  • 60
  • 77
4

Found a round about to solve this problem. This seems to answer the question I asked.

ffprobe -i input.mp4 -show_streams 2>&1 | grep 'Stream #0:1'
guerda
  • 23,388
  • 27
  • 97
  • 146
Kartos
  • 749
  • 1
  • 7
  • 18
  • 1
    That's ok if you're sure that your audio is always gonna be your 2nd stream. – AJ29 Feb 05 '14 at 00:46
  • Had to resort to this only because select_streams isn't working on my server. First, I thought it was because of an older version of ffmpeg et. al. and hence updated ffmpeg + dependants to the latest version. I still run into the same issues. Any idea why? – Kartos Feb 05 '14 at 02:46
  • No, I'm clueless :( The command line in my answer works perfectly fine on my machine (I'm using ffprobe version N-56254-gb7bd688)... – AJ29 Feb 05 '14 at 03:20
  • Yes, the command works perfect on my local machine too. However, for some reason running the same command on my Ubuntu server throws: Unrecognized option 'show_streams' Failed to set value '-select_streams' for option 'show_streams' and I'm running ffprobe version 1.0.1 built on Jan 10 2013. – Kartos Feb 05 '14 at 05:47
  • If the select stream is important to you then you should definitely try with a newer version, if not then leave it as it is ;) – AJ29 Feb 05 '14 at 21:00
2

If you only want to know if there is audio and don't care about the stream details you can run the following command, which will extract the duration of the audio stream in the input file. If the response is null/whitespace the input file has no audio in it.

Command:

ffprobe -v error -of flat=s_ -select_streams 1 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1
sebastian.roibu
  • 2,579
  • 7
  • 37
  • 59
2
ffprobe -v fatal                         # set log level to fatal
        -of default=nw=1:nk=1            # use default format and hide wrappers and keys
        -show_streams                    # show info about media streams
        -select_streams a                # show only audio streams
        -show_entries stream=codec_type  # show only stream.codec_type entries
        video.mp4                        # input file

A media file contains an audio stream returns:

audio
1
0
0
0
0
0
0
0
0
0
0
0
und
SoundHandler

A media file contains no audio stream retuns empty result.

A non-media file also returns empty result. If you want to return an error message for non-media files and on any other error case, use -v error instead:

ffprobe -v error                         # set log level to error
        -of default=nw=1:nk=1            # use default format and hide wrappers and keys
        -show_streams                    # show info about media streams
        -select_streams a                # show only audio streams
        -show_entries stream=codec_type  # show only stream.codec_type entries
        video.mp4                        # input file

So, you take this instead of empty result:

non-media-file.zip: Invalid data found when processing input
mmdemirbas
  • 9,060
  • 5
  • 45
  • 53