FFMPEG仅在写入管道时引发异常



我目前正在用Python编写一个小型应用程序,该应用程序从Youtube Link获取音频,并将其转换为波形数据以进行可视化。我正在使用Pafy来获得合适的URL、用于转换的ffmpeg-python和用于可视化的matplotlib。

目前,我正试图跳过将文件下载到本地目录的步骤,而是希望将其直接写入ffmpeg的管道中,这样我就可以直接处理它。

功能如下:

import pafy
import os
import ffmpeg
import numpy as np
import matplotlib.pyplot as plt
import wave
def getaudio(url, filename='temp.wav'):
if os.path.exists(filename):
os.remove(filename)
source = pafy.new(url).getbestaudio(preftype='m4a').url
try:
out, _ = (
ffmpeg.input(source)
.output(filename, format='wav')
.run(capture_stdout=True, capture_stderr=True)
)
except ffmpeg._run.Error as e:
print(e.stderr.decode('utf-8'))
raise e
w = wave.open('temp.wav', 'r').readframes(-1)
audio = np.frombuffer(w, dtype=np.int16)
return audio

url = 'https://www.youtube.com/watch?v=bhZs3ALdL7Y'
audio = getaudio(url)
plt.plot(audio)
plt.show()

这通常是有效的,但它做了两件事:它返回音频,这样就可以用wave包打开它,它还将其保存为当前目录的"temp.wav",我想跳过它,用"pipe:"替换"temp.wave"输出:

try:
out, _ = (
ffmpeg.input(source)
.output('pipe:', format='wav')
.run(capture_stdout=True, capture_stderr=True)
)
except ffmpeg._run.Error as e:
print(e.stderr.decode('utf-8'))
raise e

这会引发stderr的以下输出异常:

ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 9.2.1 (GCC) 20200122
configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid 
--enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
libavutil      56. 31.100 / 56. 31.100
libavcodec     58. 54.100 / 58. 54.100
libavformat    58. 29.100 / 58. 29.100
libavdevice    58.  8.100 / 58.  8.100
libavfilter     7. 57.100 /  7. 57.100
libswscale      5.  5.100 /  5.  5.100
libswresample   3.  5.100 /  3.  5.100
libpostproc    55.  5.100 / 55.  5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'https://r4---sn-h0jelne7.googlevideo.com/videoplayback?expire=1610319670&ei=1jL7X_uZIoeC6dsP9Z6nsA8&ip=2a02%3A810d%3Aabbf%3Abeed%3A98a1%3Ae204%3A805c%3Aa5b1&id=o-AGmTIS4LdQhQz5h7nplFZ0h5iWHR3KxieH44x8mIvXab&itag=140&source=youtube&requiressl=yes&mh=dj&mm=31%2C26&mn=sn-h0jelne7%2Csn-4g5e6nzz&ms=au%2Conr&mv=m&mvi=4&pl=33&initcwndbps=1885000&vprv=1&mime=audio%2Fmp4&ns=qyAm3FG5c0DyOAH11rcQFxYF&gir=yes&clen=55649&dur=3.459&lmt=1508976590967371&mt=1610297792&fvip=4&keepalive=yes&c=WEB&n=YvU_SOWuTrPG1W&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRAIgLR-oEO3oWoBfBGslerzo-jO57JhY-xbfKxQJ1GcnpscCIAhuoixcr1X_uDGiUuJ5IbPD2zynF-R8Qp5BjQqSWUaF&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhAO9pxuDZZeOd6pESsk4tjlpzDJeCnSqPv4G1-zJKoDI1AiEAjjwkSBZeeEivgAU_DRdnI-GokWQ3P-6gKhdGHe9Za7o%3D&ratebypass=yes':
Metadata:
major_brand     : dash
minor_version   : 0
compatible_brands: iso6mp41
creation_time   : 2017-10-26T00:09:50.000000Z
Duration: 00:00:03.46, start: 0.000000, bitrate: 128 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
Metadata:
creation_time   : 2017-10-26T00:09:50.000000Z
handler_name    : SoundHandler
Stream mapping:
Stream #0:0 -> #0:0 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, wav, to 'pipe:':
Metadata:
major_brand     : dash
minor_version   : 0
compatible_brands: iso6mp41
ISFT            : Lavf58.29.100
Stream #0:0(und): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s (default)
Metadata:
creation_time   : 2017-10-26T00:09:50.000000Z
handler_name    : SoundHandler
encoder         : Lavc58.54.100 pcm_s16le
size=     596kB time=00:00:03.45 bitrate=1411.4kbits/s speed= 316x
video:0kB audio:596kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.012781%
Traceback (most recent call last):
File "e:/Coding Projects/YTStream/Test2.py", line 27, in <module>
audio = getaudio(url)
File "e:/Coding Projects/YTStream/Test2.py", line 20, in getaudio
raise e
File "e:/Coding Projects/YTStream/Test2.py", line 16, in getaudio
.run(capture_stdout=True, capture_stderr=True)
File "C:Usersxxxanaconda3libsite-packagesffmpeg_run.py", line 325, in run
raise Error('ffmpeg', out, err)
ffmpeg._run.Error: ffmpeg error (see stderr output for detail)

我很困惑如何处理这个异常,因为这里没有明显的错误消息(至少对我来说(。它只是停止,而不是当我给出一个明显的错误时(比如ffmpeg格式不支持的无效格式(。非常感谢您的帮助!

我通过直接使用FFMPEG而不是使用FFMPEG python库来解决这个问题。我仍然不确定错误的确切原因,但由于Python、Pafy、FFMPEG和源url都能工作,我认为库中存在错误。请参阅此处更新的代码:

import pafy
import os
import subprocess as sp
import io
import wave
import numpy as np
def getaudio(url):
source = pafy.new(url).getbestaudio()
command = (
['ffmpeg.exe',
'-i', source.url,
'-f', 'wav',
'-']
)
proc = sp.Open(command, stdout=sp.PIPE)
out = proc.stdout.read()
w = wave.open(io.BytesIO(out))  # Converts bytes-stream to file-like
audio = np.frombuffer(w.readframes(w.getnframes()), dtype=np.in16)
return audio

最新更新