如何使用ffmpeg将RTSP流仅音频部分输出到stdout,或直接读取音频帧?
解决方案汇总
一、FFmpeg命令修改方案(输出原始音频流到stdout)
你原命令的问题是保留了视频流且输出到本地HLS文件,修改后命令如下:
ffmpeg -i rtsp://你的RTSP地址 -vn -c:a pcm_s16le -f s16le -ar 44100 -ac 1 -
参数解释:
-vn:丢弃所有视频流,仅保留音频处理-c:a pcm_s16le:指定音频编码为16位小端整数PCM,属于无压缩的原始音频数据,可直接读取做响度计算-f s16le:强制输出格式为16位小端PCM-ar 44100:指定采样率为44100Hz,可根据你的摄像头实际参数调整-ac 1:指定输出为单声道,减少数据处理量- 末尾的
-:指定输出目标为stdout,而非本地文件
你可以在Python/Go中创建子进程调用该命令,持续读取stdout的二进制流,每2个字节对应一个16位整数音频采样点,直接转为数组即可做分贝分析。
以Python为例的调用逻辑:
import subprocess import numpy as np # 启动ffmpeg子进程 cmd = [ "ffmpeg", "-i", "rtsp://你的RTSP地址", "-vn", "-c:a", "pcm_s16le", "-f", "s16le", "-ar", "44100", "-ac", "1", "-" ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, bufsize=10**8) # 每次读取1秒的音频数据(44100采样点 * 2字节/采样点 = 88200字节) while True: audio_bytes = proc.stdout.read(88200) if not audio_bytes: break # 转为16位整数数组 audio_array = np.frombuffer(audio_bytes, dtype=np.int16) # 此处执行分贝计算逻辑
二、直接读取RTSP音频帧的编程方案
如果你不想依赖FFmpeg子进程调用,可以直接用对应语言的RTSP处理库实现你需要的API逻辑:
Python方案
使用PyAV库(FFmpeg的Python绑定),示例代码如下:
import av import numpy as np # 打开RTSP流 container = av.open("rtsp://你的RTSP地址") # 查找音频流 audio_stream = next(s for s in container.streams if s.type == 'audio') # 持续读取音频帧 for frame in container.decode(audio_stream): # 转为numpy数组,格式为(声道数, 采样点数量),如果是单声道可以直接flatten signal_array = frame.to_ndarray() # 执行响度分析逻辑
Go方案
使用gortsplib库结合ffmpeg-go绑定,核心逻辑如下:
package main import ( "gortsplib/v2" "gortsplib/v2/pkg/format" "gortsplib/v2/pkg/formatdecenc/rtppcmalaw" ) func main() { // 初始化RTSP客户端 client := gortsplib.Client{} // 连接RTSP地址 conn, _, err := client.Dial("rtsp://你的RTSP地址") if err != nil { panic(err) } defer conn.Close() // 查找音频格式 var audioFormat *format.PCMALaw for _, forma := range conn.Setup { if f, ok := forma.Format.(*format.PCMALaw); ok { audioFormat = f break } } // 读取RTP包并解码为音频帧 conn.OnPacketRTP(audioFormat, func(pkt *rtppcmalaw.Packet) { signalArray := pkt.Payload // 执行响度分析逻辑 }) // 开始播放 conn.Play(nil) select {} }
内容的提问来源于stack exchange,提问作者J_yang
相关产品推荐
相关产品推荐

