检查视频是否有声音,即使它有音频编解码器?



我是中级python的新手,我正在尝试查找下载的视频是否有声音,我下载的每个视频都有音频编解码器,但我想获得音频在特定视频中的声音分贝。

例如,这个'FFmpeg'命令行脚本允许我获得完整的信息:
ffmpeg -hide_banner -i testvideo.mp4 -af volumedetect -vn -f null - 2>&1

这在我的命令提示符中产生以下结果(windows用户在这里使用win11)

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testvideo.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42mp41isomavc1
creation_time : 2022-04-12T23:21:45.000000Z
Duration: 00:00:40.58, start: 0.000000, bitrate: 4104 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080, 3846 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
Metadata:
creation_time : 2022-04-12T23:21:45.000000Z
handler_name : L-SMASH Video Handler
vendor_id : [0][0][0][0]
encoder : AVC Coding
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 253 kb/s (default)
Metadata:
creation_time : 2022-04-12T23:21:45.000000Z
handler_name : L-SMASH Audio Handler
vendor_id : [0][0][0][0]
Stream mapping:
Stream #0:1 -> #0:0 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to 'pipe:':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42mp41isomavc1
encoder : Lavf59.35.100
Stream #0:0(und): Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s (default)
Metadata:
creation_time : 2022-04-12T23:21:45.000000Z
handler_name : L-SMASH Audio Handler
vendor_id : [0][0][0][0]
encoder : Lavc59.56.100 pcm_s16le
size=N/A time=00:00:40.55 bitrate=N/A speed=1.22e+03x
video:0kB audio:7608kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[Parsed_volumedetect_0 @ 0000026609be08c0] n_samples: 3895296
[Parsed_volumedetect_0 @ 0000026609be08c0] mean_volume: -91.0 dB
[Parsed_volumedetect_0 @ 0000026609be08c0] max_volume: -91.0 dB
[Parsed_volumedetect_0 @ 0000026609be08c0] histogram_91db: 3895296

正如你所看到的,有'parsed_volumedetect'值,dB的平均值为-91 dB,这意味着音频没有声音,即视频有音频,但没有声音。

现在我正试图在python中做同样的事情,我想要得到存储在变量中的平均音量值,以便我可以检查视频中是否有任何声音。

到目前为止,我已经看到了子进程代码,但是当我尝试在VS-Code - python 3.11中运行我的代码时:

import subprocess    
result = subprocess.run(["ffmpeg", "-hide_banner", "-af", "volumedetect", "-vn", "-f", "null", "testvideo1.mp4"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True)
print(result.stdout)

上面写着:

PS C:UsersbalajOneDriveDocumentsProgramming languagepython files> c:; cd 'c:UsersbalajOneDriveDocumentsProgramming languagepython files'; & 'C:Python311python.exe' 'c:Usersbalaj.vscodeextensionsms-python.python-2022.20.2pythonFileslibpythondebugpyadapter/../..debugpylauncher' '51760' '--' 'c:UsersbalajOneDriveDocumentsProgramming languagepython filesdevprojectsample.py'
b"Output #0, null, to 'testvideo1.mp4':rnOutput file #0 does not contain any streamrn"

任何帮助都是非常感激的。很抱歉写了这么长时间……TIA ! !只是一个快速更新:对于有声音的视频文件(我在VLC中测试过)和没有声音的视频文件,结果是相同的。

另一个更新:我已经将subprocess.run代码更改为与我在cmd窗口中调用的完全相同:

result = subprocess.run(["ffmpeg", "-hide_banner","-i","testvideo-sound.mp4", "-af", "volumedetect", "-vn", "-f", "null", "-2>&1"]

现在结果是:

b'The handle could not be duplicatedrnduring redirection of handle 1.rn'

这似乎对我有用。我用我身边的几个不同的视频文件(mp4)试了试。

import subprocess
import re
files = [
# list of file paths
]
def find_volume(s):
# regex to find volume in a string
m = re.search("(?:max_volume: )(?P<volume>.+ dB)", s, flags=re.IGNORECASE)

if not m:
return None
return m.groupdict()["volume"]

for filepath in files:
r = subprocess.run(f'ffmpeg -i "{filepath}" -filter:a volumedetect -f null /dev/null',
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True
)
# "volume" will be either None or a string;
# if it is none, we go to do to the "else" body
# instead, because None if 'falsy'.
if volume := find_volume(r.stdout.decode("utf-8")):
print(f'Video file "{filepath}" has a max volume of {volume}')
else:
print(f'Video file "{filepath}" has no audio')

最新更新