Reputation: 1143
I would just like a True
if a video has audio or False
if it does not have audio.
I feel like I'm almost there using subprocess.
I get info about the video file running ffprobe
and splitting the results into a list.
I've tried matching a string that does or does not have audio in the list but this is not giving me consistant results.
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])
The line above checks if there is a second stream in the video file in the 20th from the last line. Like I said, not always consistent.
I'm just having trouble requesting or parsing what I'm getting from ffmprobe
.
Here is everything returned from ffprobe
instead of just the 20th from the last item.
b = '/path/to/mp4'
subprocess.run(['ffprobe', b], stdout=PIPE, stderr=PIPE).stderr.split()
returns...
[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']
I have also tried modifying this function from one that returns the duration of video files to one that returns True
or False
for audio because this is probably a less hacky way of getting the bool. I'm a bit out of my depth trying to use these different options.
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)
Upvotes: 3
Views: 5227
Reputation: 5658
One can use pymediainfo module for this.
def has_audio(p):
from pymediainfo import MediaInfo
fileInfo = MediaInfo.parse(p)
return any([track.track_type == 'Audio' for track in fileInfo.tracks])
Upvotes: 1
Reputation: 441
Building on previous answers, this will check each stream to see if at least one has an "audio" type codec. Please note that an audio stream may be present but silent, in which case this will still return 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
Upvotes: 3
Reputation: 1143
I believe I found the option to sort any video file with an output of 1
(for True
, has sound), or 0
(for False
, does not have sound) by passing nb_streams
in the format
option below.
Used a combination of this answer and the docs for ffmpeg to figure this out.
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)
The code actually returns the number of streams. 2
for two streams, video and audio, or 1
for just video. I subtracted a one because I want the bool answer.
This should probably not be used to sort audio only files. Though I wonder if 1
for just video and 2
for audio and video is always the case for known video files. Can a video file have 3 or more streams?
Upvotes: 4
Reputation: 5
The answer isn't too hard.
pip3 install ffprobe
pip install ffprobe
pip install ffprobe
ffprobe -show_streams -print_format json input.mov
should work.
Upvotes: 0