如何正确地将Pytube bufferIO转换为表示正弦波的numpy数组?

dwbf0jvd  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(98)

问题:我试图通过Pytube从Youtube下载音频,将其保存到缓冲区(我不想将音频保存到驱动器),然后将其转换为numpy数组,以便绘制原始音频波。转换后,我试图将其转换回声音,而不是12分钟的音频从视频,我得到12秒的静态噪音。当将缓冲区保存到.mp4时,一切似乎都工作得很好。我迷路了,如果有人帮忙我会很感激的。
程序

from IPython.display import Audio
from pytube import YouTube
import numpy as np
from io import BytesIO

yt = YouTube('https://www.youtube.com/watch?v=zrqqrQmeQS4')

# getting audio stream
audioStreams = list(map(lambda streamObj: streamObj.itag, yt.streams.filter(only_audio=True)))
activeStream = yt.streams.get_by_itag(audioStreams[0])

# saving to buffer
bufferObj = BytesIO()
activeStream.stream_to_buffer(bufferObj)

# saving buffer to ndarray
bufferObj.seek(0)
points_array = np.frombuffer(bufferObj.read())

# preprocessing raw numpy data
points_array = np.round(points_array,10)
points_array[np.isinf(points_array) | np.isnan(points_array)] = 0

return Audio(points_array, rate=44.1 * 1000)

字符串

v7pvogib

v7pvogib1#

让我们解决几个问题:

1.points_array = np.frombuffer(bufferObj.read())

通过这一行,您将获得的数据(字节)解释为float64,这是np.frombuffer * 的默认dtype(如在docs中所见)*。您想要处理的音频数据通常以16-bit PCM等格式存储。为了解决潜在的问题,我们需要使用一个知道如何正确解释音频数据的模块。我使用pydub将音频转换为WAV格式,然后可以通过scipy读取。

2.points_array = np.round(points_array,10)

与之前类似,这意味着音频数据是浮点格式的,但它不是。如前所述,我们使用整数格式(如有符号16位PCM)。关于题外话:如果您试图规范化音频数据 (“预处理”),您应该将其除以最大可能值(因此对于16位,它将是2^15 - 1 = 32767

3.return Audio(points_array, rate=44.1 * 1000)

最后,这种硬编码的速度对你没有好处。您应该提取采样率(使用scipy阅读音频时)。
现在整个剧本都在运作。下面是完整的代码(包括上面指定的固定行):

from pytube import YouTube
from pydub import AudioSegment
from io import BytesIO
from scipy.io.wavfile import read as wav_read
import numpy as np
from IPython.display import Audio

yt = YouTube('https://www.youtube.com/watch?v=zrqqrQmeQS4')

# Getting audio stream
audioStreams = list(map(lambda streamObj: streamObj.itag, yt.streams.filter(only_audio=True)))
activeStream = yt.streams.get_by_itag(audioStreams[0])

# Saving to buffer
bufferObj = BytesIO()
activeStream.stream_to_buffer(bufferObj)

# Using pydub to read audio data from the buffer
audio = AudioSegment.from_file(bufferObj, format="mp4")

# Convert audio to wav format and then save it to a new buffer
bufferObj = BytesIO()
audio.export(bufferObj, format="wav")
bufferObj.seek(0)

# Now we can properly load this into numpy
sample_rate, audio_array = wav_read(bufferObj)

# Preprocessing raw numpy data
audio_array = np.round(audio_array,10)
audio_array[np.isinf(audio_array) | np.isnan(audio_array)] = 0

# Display the audio
Audio(audio_array, rate=sample_rate)

字符串
注意:不要忘记安装pydubscipy以使其工作。
顺便说一下,在写答案的过程中,由于YouTube最近的变化,我遇到了一些问题。我通过搜索pytube目录的位置来跟踪issue #1707中的修复。

>>> import pytube
>>> print(pytube.__file__)


然后将线r'var {nfunc}\s*=\s*(\[.+?\]);'.format(改变为r'var {nfunc}\s*=\s*(\[.+?\])'.format((即,从RegEx语句中删除;)。

omqzjyyz

omqzjyyz2#

可以使用soundfile
SoundFile可以读取和写入声音文件。libsndfile是一个免费的、跨平台的开源(LGPL)库,用于读取和写入许多不同的采样声音文件格式,这些文件格式可以在许多平台上运行,包括Windows、OS X和Unix。它通过CFFI访问,CFFI是Python调用C代码的外部函数接口。CPython 2.6+、3.x和PyPy 2.0+支持CFFI。SoundFile将音频数据表示为NumPy数组。

from IPython.display import Audio
from pytube import YouTube
import numpy as np
from io import BytesIO
import soundfile as sf

yt = YouTube('https://www.youtube.com/watch?v=zrqqrQmeQS4')

# Getting audio stream
audioStreams = list(map(lambda streamObj: streamObj.itag, yt.streams.filter(only_audio=True)))
activeStream = yt.streams.get_by_itag(audioStreams[0])

# Saving to buffer
bufferObj = BytesIO()
activeStream.stream_to_buffer(bufferObj)

# Seek to the beginning of the buffer
bufferObj.seek(0)

# Convert buffer to audio data using soundfile
audio_data, sample_rate = sf.read(bufferObj)

# Preprocessing raw audio data
audio_data = np.round(audio_data, 10)
audio_data[np.isinf(audio_data) | np.isnan(audio_data)] = 0

# Display audio using IPython's Audio
return Audio(audio_data, rate=sample_rate)

字符串

相关问题