使用 AudioDecoder 解码音频流#

在本示例中,我们将学习如何使用 torchcodec.decoders.AudioDecoder 类解码音频文件。

准备工作#

首先做一些准备:我们从网上下载一个音频文件并定义一个音频播放工具。你可以忽略这部分,直接跳到“创建解码器”章节。

音频来源为 CC0: https://opengameart.org/content/town-theme-rpg

署名:cynicmusic.com pixelsphere.org

import httpx
from IPython.display import Audio

def play_audio(samples):
    return Audio(samples.data, rate=samples.sample_rate)

url = "https://opengameart.org/sites/default/files/TownTheme.mp3"
response = httpx.get(url, headers={"User-Agent": ""})
if response.status_code != 200:
    raise RuntimeError(f"Failed to download video. {response.status_code = }.")

raw_audio_bytes = response.content

创建解码器#

我们可以直接从原始(编码后的)音频字节创建一个解码器。你当然也可以使用本地音频文件并将路径作为输入传入。还可以从视频中解码音频流!

from torchcodec.decoders import AudioDecoder

decoder = AudioDecoder(raw_audio_bytes)

元数据#

此时解码器尚未实际解码,但我们已经可以通过 metadata 属性获取一些元信息,该属性是一个 torchcodec.decoders.AudioStreamMetadata 对象。

print(decoder.metadata)
AudioStreamMetadata:
  duration_seconds_from_header: 97.454014
  begin_stream_seconds_from_header: 0.025057
  bit_rate: 108039.0
  codec: mp3
  stream_index: 0
  sample_rate: 44100
  num_channels: 2
  sample_format: fltp

解码样本#

要获取解码后的样本,只需调用 AudioDecoder.get_all_samples 方法,它会返回一个 torchcodec.AudioSamples 对象:

samples = decoder.get_all_samples()

print(samples)
play_audio(samples)
AudioSamples:
  data (shape): torch.Size([2, 4297722])
  pts_seconds: 0.02505668934240363
  duration_seconds: 97.45401360544217
  sample_rate: 44100
  • .data 字段是形状为 (num_channels, num_samples) 的张量,浮点类型,取值范围为 [-1, 1]。

  • .pts_seconds 字段表示输出样本的起始时间。这里是 0.025 秒,即使我们请求从 0 开始。并非所有流都恰好从 0 开始;这源自文件在编码时的属性,并不是 TorchCodec 的问题。

指定范围#

如果不需要全部样本,可以使用 AudioDecoder.get_samples_played_in_range 在自定义区间内解码样本:

samples = decoder.get_samples_played_in_range(start_seconds=10, stop_seconds=70)

print(samples)
play_audio(samples)
AudioSamples:
  data (shape): torch.Size([2, 2646000])
  pts_seconds: 10.0
  duration_seconds: 60.0
  sample_rate: 44100

自定义采样率#

也可以在构造 AudioDecoder 时通过 sample_rate 参数指定期望的采样率。输出听起来会相似,但样本数量会明显减少:

decoder = AudioDecoder(raw_audio_bytes, sample_rate=16_000)
samples = decoder.get_all_samples()

print(samples)
play_audio(samples)
AudioSamples:
  data (shape): torch.Size([2, 1559264])
  pts_seconds: 0.02505668934240363
  duration_seconds: 97.454
  sample_rate: 16000