Я новичок в промежуточном питоне, и я пытаюсь выяснить, есть ли звук в загруженном видео, каждое загружаемое видео имеет аудиокодек, но я хочу получить децибел звука, который звук имеет в этом конкретном видео.
Например, этот скрипт командной строки «FFmpeg» позволяет мне получить полную информацию:
ffmpeg -hide_banner -i testvideo.mp4 -af volumedetect -vn -f null - 2>&1
это дает следующий результат в моей командной строке (здесь пользователь Windows с win 11)
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» с дБ, которые имеют среднее значение -91 дБ, что означает, что в аудио нет звука, то есть в видео есть звук, но нет звука.
Теперь я пытаюсь сделать то же самое в 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:\Users\balaj\OneDrive\Documents\Programming language\python files> c:; cd 'c:\Users\balaj\OneDrive\Documents\Programming language\python files'; & 'C:\Python311\python.exe' 'c:\Users\balaj\.vscode\extensions\ms-python.python-2022.20.2\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '51760' '--' 'c:\Users\balaj\OneDrive\Documents\Programming language\python files\devproject\sample.py'
b"Output #0, null, to 'testvideo1.mp4':\r\nOutput file #0 does not contain any stream\r\n"
Буду признателен за любую оказанную помощь. Извините за длинный пост... 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 duplicated\r\nduring redirection of handle 1.\r\n'
Кажется, это работает для меня. Я попробовал это с несколькими разными видеофайлами (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')