You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中播放RTSP流中的音频?附现有视频播放代码

解决RTSP音频播放问题

要实现RTSP音频的播放,你可以结合QAudioOutput处理音频帧输出,同时需要把python-av解码出的浮点planar格式音频转换为PyQt音频输出支持的格式。以下是修改后的完整代码:

import sys
import av
import numpy as np
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer
from PyQt5.QtMultimedia import QAudioOutput, QAudioFormat


class VideoStreamWidget(QWidget):
    def __init__(self, rtsp_url_local):
        super().__init__()
        self.setWindowTitle('RTSP Stream')
        self.setGeometry(100, 100, 640, 480)
        self.layout = QVBoxLayout()
        self.label = QLabel('Waiting for video stream...')
        self.layout.addWidget(self.label)
        self.setLayout(self.layout)

        # 打开RTSP流
        self.container = av.open(rtsp_url_local)
        self.video_stream = self.container.streams.video[0]
        self.audio_stream = self.container.streams.audio[0]
        print(self.audio_stream)

        # 初始化音频格式,匹配流参数
        self.audio_format = QAudioFormat()
        self.audio_format.setSampleRate(self.audio_stream.sample_rate)
        self.audio_format.setChannelCount(self.audio_stream.channels)
        self.audio_format.setSampleType(QAudioFormat.Float)
        self.audio_format.setSampleSize(32)
        self.audio_format.setByteOrder(QAudioFormat.LittleEndian)
        self.audio_format.setCodec("audio/pcm")

        # 创建音频输出对象并启动
        self.audio_output = QAudioOutput(self.audio_format)
        self.audio_io = self.audio_output.start()

        # 视频更新定时器
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_image)
        self.timer.start(16.5)

        # 音频更新定时器(按音频帧间隔调整)
        self.audio_timer = QTimer()
        self.audio_timer.timeout.connect(self.update_audio)
        self.audio_timer.start(10)

    def update_audio(self):
        try:
            for frame in self.container.decode(self.audio_stream):
                # 将planar格式转成interleaved格式
                audio_data = frame.to_ndarray()
                # 单声道直接扁平化,多声道需转置后扁平化
                interleaved_data = audio_data.flatten() if self.audio_stream.channels == 1 else audio_data.transpose().flatten()
                # 转成字节数据写入音频输出设备
                byte_data = interleaved_data.astype(np.float32).tobytes()
                self.audio_io.write(byte_data)
                break  # 每次只处理一帧,避免音频堆积
        except Exception as e:
            print(f"音频处理错误: {e}")

    def update_image(self):
        try:
            for frame in self.container.decode(self.video_stream):
                img = frame.to_image().convert("RGB")
                data = np.array(img)
                qimg = QImage(data, data.shape[1], data.shape[0], QImage.Format_RGB888)
                self.label.setPixmap(QPixmap.fromImage(qimg))
                break
        except Exception as e:
            print(f"视频处理错误: {e}")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    rtsp_url = 'rtsp://192.168.1.18:554/video=0,audio=0'  # 示例RTSP地址
    video_stream_widget = VideoStreamWidget(rtsp_url)
    video_stream_widget.show()
    sys.exit(app.exec_())

关键细节说明

  • 音频格式匹配:必须严格对齐RTSP流的音频参数(采样率、声道数、采样类型),否则会出现杂音或无法播放的问题。
  • 格式转换:python-av解码的音频是planar格式(每个声道单独存储),而QAudioOutput需要interleaved格式(声道数据交错存储),通过数组转置和扁平化完成转换。
  • 节奏控制:音频定时器间隔设置为10ms左右,每次只处理一帧,避免音频数据堆积导致播放延迟。
  • 异常捕获:添加异常处理防止单帧解码错误导致程序崩溃。

内容的提问来源于stack exchange,提问作者qTp_Meteor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:58:19