【问题标题】:How to check if a video has sound in Python?如何在 Python 中检查视频是否有声音?
【发布时间】:2021-01-22 16:46:06
【问题描述】:

如果视频有音频,我想要True,如果没有音频,我想要False

我觉得我几乎可以使用子流程了。

我获得了有关运行 ffprobe 的视频文件的信息,并将结果拆分为一个列表。
我尝试匹配列表中包含或不包含音频的字符串,但这并没有给我一致的结果。

from subprocess import Popen, PIPE
import subprocess

b = '/path/to/mp4'
'0:1' in str(subprocess.run(['ffprobe', b], stdout=PIPE, stderr=PIPE).stderr.split()[-20])  

上面的行检查视频文件中从最后一行算起的第 20 个是否有第二个流。就像我说的,并不总是一致的。
我只是在请求或解析我从 ffmprobe 获得的内容时遇到了问题。

这是从ffprobe 返回的所有内容,而不是最后一项的第 20 个。

b = '/path/to/mp4'
subprocess.run(['ffprobe', b], stdout=PIPE, stderr=PIPE).stderr.split()  

返回...

[b'ffprobe',
 b'version',
 b'4.2.4-1ubuntu0.1',
 b'Copyright',
 b'(c)',
 b'2007-2020',
 b'the',
 b'FFmpeg',
 b'developers',
 b'built',
 b'with',
 b'gcc',
 b'9',
 b'(Ubuntu',
 b'9.3.0-10ubuntu2)',
 b'configuration:',
 b'--prefix=/usr',
 b'--extra-version=1ubuntu0.1',
 b'--toolchain=hardened',
 b'--libdir=/usr/lib/x86_64-linux-gnu',
 b'--incdir=/usr/include/x86_64-linux-gnu',
 b'--arch=amd64',
 b'--enable-gpl',
 b'--disable-stripping',
 b'--enable-avresample',
 b'--disable-filter=resample',
 b'--enable-avisynth',
 b'--enable-gnutls',
 b'--enable-ladspa',
 b'--enable-libaom',
 b'--enable-libass',
 b'--enable-libbluray',
 b'--enable-libbs2b',
 b'--enable-libcaca',
 b'--enable-libcdio',
 b'--enable-libcodec2',
 b'--enable-libflite',
 b'--enable-libfontconfig',
 b'--enable-libfreetype',
 b'--enable-libfribidi',
 b'--enable-libgme',
 b'--enable-libgsm',
 b'--enable-libjack',
 b'--enable-libmp3lame',
 b'--enable-libmysofa',
 b'--enable-libopenjpeg',
 b'--enable-libopenmpt',
 b'--enable-libopus',
 b'--enable-libpulse',
 b'--enable-librsvg',
 b'--enable-librubberband',
 b'--enable-libshine',
 b'--enable-libsnappy',
 b'--enable-libsoxr',
 b'--enable-libspeex',
 b'--enable-libssh',
 b'--enable-libtheora',
 b'--enable-libtwolame',
 b'--enable-libvidstab',
 b'--enable-libvorbis',
 b'--enable-libvpx',
 b'--enable-libwavpack',
 b'--enable-libwebp',
 b'--enable-libx265',
 b'--enable-libxml2',
 b'--enable-libxvid',
 b'--enable-libzmq',
 b'--enable-libzvbi',
 b'--enable-lv2',
 b'--enable-omx',
 b'--enable-openal',
 b'--enable-opencl',
 b'--enable-opengl',
 b'--enable-sdl2',
 b'--enable-libdc1394',
 b'--enable-libdrm',
 b'--enable-libiec61883',
 b'--enable-nvenc',
 b'--enable-chromaprint',
 b'--enable-frei0r',
 b'--enable-libx264',
 b'--enable-shared',
 b'libavutil',
 b'56.',
 b'31.100',
 b'/',
 b'56.',
 b'31.100',
 b'libavcodec',
 b'58.',
 b'54.100',
 b'/',
 b'58.',
 b'54.100',
 b'libavformat',
 b'58.',
 b'29.100',
 b'/',
 b'58.',
 b'29.100',
 b'libavdevice',
 b'58.',
 b'8.100',
 b'/',
 b'58.',
 b'8.100',
 b'libavfilter',
 b'7.',
 b'57.100',
 b'/',
 b'7.',
 b'57.100',
 b'libavresample',
 b'4.',
 b'0.',
 b'0',
 b'/',
 b'4.',
 b'0.',
 b'0',
 b'libswscale',
 b'5.',
 b'5.100',
 b'/',
 b'5.',
 b'5.100',
 b'libswresample',
 b'3.',
 b'5.100',
 b'/',
 b'3.',
 b'5.100',
 b'libpostproc',
 b'55.',
 b'5.100',
 b'/',
 b'55.',
 b'5.100',
 b'Input',
 b'#0,',
 b'mov,mp4,m4a,3gp,3g2,mj2,',
 b'from',
 b"'/media/iii/Q2/tor/Reddit/Subs/unexpected/l2aifial2ir51.mp4':",
 b'Metadata:',
 b'major_brand',
 b':',
 b'isom',
 b'minor_version',
 b':',
 b'512',
 b'compatible_brands:',
 b'isomiso2avc1mp41',
 b'encoder',
 b':',
 b'Lavf58.29.100',
 b'Duration:',
 b'00:00:16.27,',
 b'start:',
 b'0.000000,',
 b'bitrate:',
 b'1341',
 b'kb/s',
 b'Stream',
 b'#0:0(und):',
 b'Video:',
 b'h264',
 b'(Main)',
 b'(avc1',
 b'/',
 b'0x31637661),',
 b'yuv420p,',
 b'384x480',
 b'[SAR',
 b'1:1',
 b'DAR',
 b'4:5],',
 b'1205',
 b'kb/s,',
 b'30',
 b'fps,',
 b'30',
 b'tbr,',
 b'12k',
 b'tbn,',
 b'60',
 b'tbc',
 b'(default)',
 b'Metadata:',
 b'handler_name',
 b':',
 b'Bento4',
 b'Video',
 b'Handler',
 b'Stream',
 b'#0:1(und):',
 b'Audio:',
 b'aac',
 b'(LC)',
 b'(mp4a',
 b'/',
 b'0x6134706D),',
 b'48000',
 b'Hz,',
 b'stereo,',
 b'fltp,',
 b'128',
 b'kb/s',
 b'(default)',
 b'Metadata:',
 b'handler_name',
 b':',
 b'Bento4',
 b'Sound',
 b'Handler']  

我还尝试将这个函数从返回视频文件持续时间的函数修改为返回 TrueFalse 用于音频的函数,因为这可能是获取布尔值的一种不那么老套的方法。尝试使用这些不同的选项时,我有点不知所措。

def get_length(filename):
    result = subprocess.run(["ffprobe", "-v", "error", "-show_entries",
                             "format=duration", "-of",
                             "default=noprint_wrappers=1:nokey=1", filename],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    return float(result.stdout)

【问题讨论】:

  • 这能回答你的问题吗? Using ffprobe to check audio-only files
  • 似乎更多的是为 ffprobe 使用正确的参数而不是 Python 问题。
  • @mkrieger1 谢谢,但不,不完全是。这是针对“使用 ffprobe 检查纯音频文件”。此外,它似乎不适用于 Python。它很有用,如果我破解它一两个小时,我可能会从那个答案中得到我想要的。
  • @mkrieger1 "for ffprobe 而不是 Python 问题" 我只是在使用 ffprobe,因为这就是我尝试过的。我知道最好不要在没有发布尝试的情况下在 StackOverflow 上提问。我需要检查视频是否在 Python 中有音频。有或没有 ffprobe 但在 Python 中。不是命令行。
  • 答案中显示的命令告诉您文件是否具有视频音频,它在两种情况下都有效。它返回一个可以在 Python 中轻松解析的 JSON 数据结构,请参阅stackoverflow.com/questions/7771011/how-to-parse-json-in-python

标签: python subprocess ffprobe


【解决方案1】:

我相信我找到了通过传递@987654327 对输出为1(对于True,有声音)或0(对于False,没有声音)的任何视频文件进行排序的选项@ 在下面的format 选项中。
this answerdocs 组合用于ffmpeg 来解决这个问题。

def has_audio(filename):
    result = subprocess.run(["ffprobe", "-v", "error", "-show_entries",
                             "format=nb_streams", "-of",
                             "default=noprint_wrappers=1:nokey=1", filename],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    return (int(result.stdout) -1)

代码实际上返回了流的数量。 2 用于两个流,视频和音频,或1 仅用于视频。我减去了一个,因为我想要布尔答案。
这可能不应该用于对仅音频文件进行排序。尽管我想知道1 仅用于视频,2 用于音频和视频是否始终适用于已知视频文件。一个视频文件可以有 3 个或更多流吗?

【讨论】:

  • 是的,一个视频文件可以有 3 个以上的流(例如多种语言的音轨)。感谢有用的 Python 包装器分解!
【解决方案2】:

答案并不难。

MAC

pip3 install ffprobe

Windows

pip install ffprobe

Linux

pip install ffprobe

用法

ffprobe -show_streams -print_format json input.mov 应该可以工作。

【讨论】:

  • 谢谢。但是在 Python 中呢?我试图将其调整为像 subprocess.run(["ffprobe", "-show_streams", "-print_format", "json", b], stdout=PIPE, stderr=PIPE) 这样的子流程,但 Python 说类型仍然是 subprocess.CompletedProcess
【解决方案3】:

在之前的答案的基础上,这将检查每个流以查看是否至少有一个具有“音频”类型的编解码器。请注意,音频流可能存在但无声,在这种情况下仍将返回 True。

from subprocess import check_output
import json

def has_audio_streams(file_path):
  command = ['ffprobe', '-show_streams',
           '-print_format', 'json', file_path]
  output = check_output(command)
  parsed = json.loads(output)
  streams = parsed['streams']
  audio_streams = list(filter((lambda x: x['codec_type'] == 'audio'), streams))
  return len(audio_streams) > 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2020-04-17
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多