注意
點選 此處 下載完整示例程式碼
StreamWriter 高階用法¶
作者: Moto Hira
本教程展示瞭如何使用 torchaudio.io.StreamWriter 播放音訊和影片。
注意
本教程使用硬體裝置,因此在不同作業系統上不可移植。
本教程在 MacBook Pro (M1, 2020) 上編寫和測試。
注意
本教程需要 FFmpeg 庫。詳情請參閱 FFmpeg 依賴。
警告
TorchAudio 動態載入系統上安裝的相容 FFmpeg 庫。支援的格式型別(媒體格式、編碼器、編碼器選項等)取決於這些庫。
要檢查可用的裝置、混流器和編碼器,可以使用以下命令
ffmpeg -muxers
ffmpeg -encoders
ffmpeg -devices
ffmpeg -protocols
準備¶
import torch
import torchaudio
print(torch.__version__)
print(torchaudio.__version__)
from torchaudio.io import StreamWriter
from torchaudio.utils import download_asset
AUDIO_PATH = download_asset("tutorial-assets/Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav")
VIDEO_PATH = download_asset(
"tutorial-assets/stream-api/NASAs_Most_Scientifically_Complex_Space_Observatory_Requires_Precision-MP4_small.mp4"
)
裝置可用性¶
StreamWriter 利用了 FFmpeg 的 IO 抽象,將資料寫入揚聲器和 GUI 等媒體裝置。
要寫入裝置,請在 StreamWriter 的建構函式中提供 format 選項。
不同作業系統有不同的裝置選項,其可用性取決於 FFmpeg 的實際安裝情況。
要檢查哪些裝置可用,可以使用 ffmpeg -devices 命令。
“audiotoolbox”(揚聲器)和“sdl”(影片 GUI)可用。
$ ffmpeg -devices
...
Devices:
D. = Demuxing supported
.E = Muxing supported
--
E audiotoolbox AudioToolbox output device
D avfoundation AVFoundation input device
D lavfi Libavfilter virtual input device
E opengl OpenGL output
E sdl,sdl2 SDL2 output device
有關哪些作業系統上可用哪些裝置的詳細資訊,請查閱 FFmpeg 官方文件:https://ffmpeg.org/ffmpeg-devices.html
播放音訊¶
透過提供 format="audiotoolbox" 選項,StreamWriter 將資料寫入揚聲器裝置。
# Prepare sample audio
waveform, sample_rate = torchaudio.load(AUDIO_PATH, channels_first=False, normalize=False)
num_frames, num_channels = waveform.shape
# Configure StreamWriter to write to speaker device
s = StreamWriter(dst="-", format="audiotoolbox")
s.add_audio_stream(sample_rate, num_channels, format="s16")
# Write audio to the device
with s.open():
for i in range(0, num_frames, 256):
s.write_audio_chunk(0, waveform[i : i + 256])
注意
寫入“audiotoolbox”是阻塞操作,但它不會等待音訊播放完成。在音訊播放時,裝置必須保持開啟狀態。
以下程式碼將在音訊寫入後立即關閉裝置,而不會等到播放完成。新增 time.sleep() 將有助於保持裝置開啟直到播放完成。
with s.open():
s.write_audio_chunk(0, waveform)
播放影片¶
要播放影片,可以使用 format="sdl" 或 format="opengl"。同樣,你需要一個啟用了相應整合的 FFmpeg 版本。可以使用 ffmpeg -devices 檢查可用裝置。
此處,我們使用 SDL 裝置 (https://ffmpeg.org/ffmpeg-devices.html#sdl)。
# note:
# SDL device does not support specifying frame rate, and it has to
# match the refresh rate of display.
frame_rate = 120
width, height = 640, 360
為此,我們定義了一個輔助函式,該函式將影片載入委託給後臺執行緒並提供資料塊
running = True
def video_streamer(path, frames_per_chunk):
import queue
import threading
from torchaudio.io import StreamReader
q = queue.Queue()
# Streaming process that runs in background thread
def _streamer():
streamer = StreamReader(path)
streamer.add_basic_video_stream(
frames_per_chunk, format="rgb24", frame_rate=frame_rate, width=width, height=height
)
for (chunk_,) in streamer.stream():
q.put(chunk_)
if not running:
break
# Start the background thread and fetch chunks
t = threading.Thread(target=_streamer)
t.start()
while running:
try:
yield q.get()
except queue.Empty:
break
t.join()
現在開始流式傳輸。按下“Q”將停止影片。
注意
對 SDL 裝置呼叫 write_video_chunk 會阻塞,直到 SDL 完成影片播放。
# Set output device to SDL
s = StreamWriter("-", format="sdl")
# Configure video stream (RGB24)
s.add_video_stream(frame_rate, width, height, format="rgb24", encoder_format="rgb24")
# Play the video
with s.open():
for chunk in video_streamer(VIDEO_PATH, frames_per_chunk=256):
try:
s.write_video_chunk(0, chunk)
except RuntimeError:
running = False
break
[程式碼]
流式傳輸影片¶
至此,我們已經瞭解瞭如何寫入硬體裝置。還有一些其他的影片流式傳輸方法。
RTMP (即時訊息傳輸協議)¶
使用 RTMP,可以將媒體(影片和/或音訊)流式傳輸到一個客戶端。這不需要硬體裝置,但需要單獨的播放器。
要使用 RTMP,請在 StreamWriter 建構函式的 dst 引數中指定協議和路由,然後在開啟目標時傳遞 {"listen": "1"} 選項。
StreamWriter 將監聽埠並等待客戶端請求影片。open 的呼叫會阻塞,直到收到請求。
s = StreamWriter(dst="rtmp://:1935/live/app", format="flv")
s.add_audio_stream(sample_rate=sample_rate, num_channels=num_channels, encoder="aac")
s.add_video_stream(frame_rate=frame_rate, width=width, height=height)
with s.open(option={"listen": "1"}):
for video_chunk, audio_chunk in generator():
s.write_audio_chunk(0, audio_chunk)
s.write_video_chunk(1, video_chunk)
[程式碼]
UDP (使用者資料報協議)¶
使用 UDP,可以將媒體(影片和/或音訊)流式傳輸到套接字。這不需要硬體裝置,但需要單獨的播放器。
與 RTMP 不同,UDP 流式傳輸與客戶端程序是斷開的。流式傳輸程序不感知客戶端程序。
s = StreamWriter(dst="udp://:48550", format="mpegts")
s.add_audio_stream(sample_rate=sample_rate, num_channels=num_channels, encoder="aac")
s.add_video_stream(frame_rate=frame_rate, width=width, height=height)
with s.open():
for video_chunk, audio_chunk in generator():
s.write_audio_chunk(0, audio_chunk)
s.write_video_chunk(1, video_chunk)
[程式碼]
標籤: torchaudio.io
指令碼總執行時間: ( 0 分鐘 0.000 秒)