How to detect audio sampling rate with avprobe / ffprobe?
Asked Answered
R

4

14

I am using libav 9.6, installed via Homebrew.

$ avprobe -version
avprobe version 9.6, Copyright (c) 2007-2013 the Libav developers
  built on Jun  8 2013 02:44:19 with Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
avprobe 9.6
libavutil     52.  3. 0 / 52.  3. 0
libavcodec    54. 35. 0 / 54. 35. 0
libavformat   54. 20. 3 / 54. 20. 3
libavdevice   53.  2. 0 / 53.  2. 0
libavfilter    3.  3. 0 /  3.  3. 0
libavresample  1.  0. 1 /  1.  0. 1
libswscale     2.  1. 1 /  2.  1. 1

Even though the sampling rate is displayed in the stdout in the command line output, the -show_format option doesn't surface the sampling rate information for the audio file at all.

Here is the BASH terminal output:

$ avprobe  -v verbose -show_format -of json  sample.gsm
avprobe version 9.6, Copyright (c) 2007-2013 the Libav developers
  built on Jun  8 2013 02:44:19 with Apple LLVM version 4.2 (clang-425.0.24)
(based on LLVM 3.2svn)
  configuration: --prefix=/usr/local/Cellar/libav/9.6 --enable-shared
--enable-pthreads --enable-gpl --enable-version3 --enable-nonfree
--enable-hardcoded-tables --enable-avresample --enable-vda --enable-gnutls
--enable-runtime-cpudetect --disable-indev=jack --cc=cc --host-cflags=
--host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame
--enable-libxvid --enable-avplay
  libavutil     52.  3. 0 / 52.  3. 0
  libavcodec    54. 35. 0 / 54. 35. 0
  libavformat   54. 20. 3 / 54. 20. 3
  libavdevice   53.  2. 0 / 53.  2. 0
  libavfilter    3.  3. 0 /  3.  3. 0
  libavresample  1.  0. 1 /  1.  0. 1
  libswscale     2.  1. 1 /  2.  1. 1
[gsm @ 0x7f8012806600] Estimating duration from bitrate, this may be inaccurate
Input #0, gsm, from 'sample.gsm':
  Duration: 00:03:52.32, start: 0.000000, bitrate: 13 kb/s
    Stream #0.0: Audio: gsm, 8000 Hz, mono, s16, 13 kb/s
{  "format" : {
    "filename" : "sample.gsm",
    "nb_streams" : 1,
    "format_name" : "gsm",
    "format_long_name" : "raw GSM",
    "start_time" : "0.000000",
    "duration" : "232.320000",
    "size" : "383328.000000",
    "bit_rate" : "13200.000000"
  }}

And the python code example:

>>> filename = 'sample.gsm'
>>> result = subprocess.check_output(['avprobe', '-show_format', '-of',
'json', filename])
avprobe version 9.6, Copyright (c) 2007-2013 the Libav developers
  built on Jun  8 2013 02:44:19 with Apple LLVM version 4.2
(clang-425.0.24) (based on LLVM 3.2svn)
[gsm @ 0x7fe0b1806600] Estimating duration from bitrate, this may be
inaccurate
Input #0, gsm, from 'sample.gsm':
  Duration: 00:03:52.32, start: 0.000000, bitrate: 13 kb/s
    Stream #0.0: Audio: gsm, 8000 Hz, mono, s16, 13 kb/s
>>> print result
{  "format" : {
    "filename" : "sample.gsm",
    "nb_streams" : 1,
    "format_name" : "gsm",
    "format_long_name" : "raw GSM",
    "start_time" : "0.000000",
    "duration" : "232.320000",
    "size" : "383328.000000",
    "bit_rate" : "13200.000000"
}}

So I am aware that sampling rate could be a stream specific display to be shown in -show_format option results. But there isn't any other options to detect the sampling rate on a specific audio stream even though it's possible to set it with -ar when re-encoding it.

I filed a ticket to libav but I am just curious if there is any other way to extract sampling rate from libav probing utils. I appreciate the answer beforehand.

PS: it would be the same question for the upstream project of ffmpeg (ffprobe) in this case.

Rudderhead answered 8/8, 2013 at 14:31 Comment(0)
C
19

-show_format shows the container-level information -- i.e. stuff that applies to all streams. Sample rate is a property of a single stream, so it's perfectly normal that -show_format doesn't display it. You need to use -show_streams.

Colatitude answered 8/8, 2013 at 15:17 Comment(2)
Perfect! Thanks for the explainatino Anton! -show_streams works :)Rudderhead
To further narrow down outputs to the audio stream, we could add -select_stream a, resulting in something like: ffprobe -select_streams a -show_streams input.flac.Wyckoff
X
4

This command can do the trick even for videos:

ffprobe -v error -select_streams a -of default=noprint_wrappers=1:nokey=1 -show_entries stream=sample_rate input.wav
Xanthin answered 17/4, 2022 at 2:56 Comment(0)
S
3

I found that the json library can parse the output from ffprobe into a dictionary, and elaborated on your code to store the information inside python. Here's a function that does this and prints the media info if you wish:

import json
from subprocess import check_output

def get_media_info(filename, print_result=True):
    """
    Returns:
        result = dict with audio info where:
        result['format'] contains dict of tags, bit rate etc.
        result['streams'] contains a dict per stream with sample rate, channels etc.
    """
    result = check_output(['ffprobe',
                            '-hide_banner', '-loglevel', 'panic',
                            '-show_format',
                            '-show_streams',
                            '-of',
                            'json', filename])

    result = json.loads(result)

    if print_result:
        print('\nFormat')

        for key, value in result['format'].items():
            print('   ', key, ':', value)

        print('\nStreams')
        for stream in result['streams']:
            for key, value in stream.items():
                print('   ', key, ':', value)

        print('\n')

    return result
Stat answered 8/7, 2019 at 12:47 Comment(0)
G
2

Following jadujoel's answer, we can do the same thing in the shell using jq (which parses json).

ffprobe -hide_banner -loglevel panic -show_format -show_streams -of json input.wav | \
  jq '.streams[0].sample_rate'

"44100"

Godfry answered 28/12, 2021 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.