使用rtsp-simple-server:Python推流网页,Chrome正常Firefox异常
问题:Python生成的视频流无法在Firefox网页中播放(Chrome正常)
更新: 流可以正常运行,但仅在Chrome中可用,Firefox无法播放。
我希望在网页上实时展示程序生成的流,为此部署了支持RTSP和HLS的rtsp-simple-server。已成功通过以下命令从文件推送流,并能在http://localhost:8888/mystream查看:
ffmpeg -re -stream_loop -1 -i file.mp4 -vcodec libx264 -f rtsp -rtsp_transport tcp rtsp://localhost:8554/mystream
但当尝试通过Python向ffmpeg标准输入推送流时,视频无限加载无法播放,Firefox控制台提示:Uncaught (in promise) DOMException: The fetching process for the media resource was aborted by the user agent at the user's request。我的Python代码如下:
import random import shlex import subprocess import time import numpy as np def main(): width = 1024 height = 720 framerate = 1 frame_duration = 1 / framerate cmd = shlex.split( f'ffmpeg' f' -y' f' -f rawvideo' f' -vcodec rawvideo' f' -s {width}x{height}' f' -pix_fmt bgr24' f' -r {framerate}' f' -i -' f' -r {framerate}' f' -force_key_frames expr:eq(mod(n,3),0)' f' -vcodec libx264' f' -crf 18' f' -preset ultrafast' f' -tune zerolatency' f' -f rtsp' f' -rtsp_transport tcp' f' rtsp://localhost:8554/mystream' ) ffmpeg_process = subprocess.Popen(cmd, stdin=subprocess.PIPE) try: while True: image = np.full( (height, width, 3), ( random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), ), dtype=np.uint8, ) ffmpeg_process.stdin.write(image.tobytes()) time.sleep(frame_duration) finally: ffmpeg_process.stdin.close() ffmpeg_process.wait() if __name__ == '__main__': main()
服务器日志中仅出现一条404(应该是网站图标favicon的请求错误,不影响),其余日志如下:
2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] GET /mystream/ 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [c->s] GET /mystream/ HTTP/1.1 Host: localhost:8888 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: ru,en-US;q=0.7,en;q=0.3 Connection: keep-alive Cookie: csrftoken=iRZDO5rsJzhh5peyyKhViN9yRslNQbuZ; Webstorm-713207de=ca4f5f1e-40e8-4bfd-97da-1be2f15f6e9e Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: cross-site Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 2023/03/25 13:50:32 INF [HLS] [muxer mystream] created (requested by 172.18.0.1) 2023/03/25 13:50:32 INF [HLS] [muxer mystream] is converting into HLS, 1 track (H264) 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [s->c] HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: text/html Server: rtsp-simple-server (body of 1240 bytes) 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] GET /favicon.ico 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [c->s] GET /favicon.ico HTTP/1.1 Host: localhost:8888 Accept: image/avif,image/webp,*/* Accept-Encoding: gzip, deflate, br Accept-Language: ru,en-US;q=0.7,en;q=0.3 Connection: keep-alive Cookie: csrftoken=iRZDO5rsJzhh5peyyKhViN9yRslNQbuZ; Webstorm-713207de=ca4f5f1e-40e8-4bfd-97da-1be2f15f6e9e Referer: http://localhost:8888/mystream/ Sec-Fetch-Dest: image Sec-Fetch-Mode: no-cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [s->c] HTTP/1.1 404 Not Found Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Server: rtsp-simple-server 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] GET /mystream/index.m3u8 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [c->s] GET /mystream/index.m3u8 HTTP/1.1 Host: localhost:8888 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: ru,en-US;q=0.7,en;q=0.3 Connection: keep-alive Cookie: csrftoken=iRZDO5rsJzhh5peyyKhViN9yRslNQbuZ; Webstorm-713207de=ca4f5f1e-40e8-4bfd-97da-1be2f15f6e9e Referer: http://localhost:8888/mystream/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 2023/03/25 13:50:32 DEB [HLS] [conn 172.18.0.1] [s->c] HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: application/x-mpegURL Server: rtsp-simple-server (body of 122 bytes) 2023/03/25 13:50:34 DEB [HLS] [conn 172.18.0.1] GET /mystream/index.m3u8 2023/03/25 13:50:34 DEB [HLS] [conn 172.18.0.1] [c->s] GET /mystream/index.m3u8 HTTP/1.1 Host: localhost:8888 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: ru,en-US;q=0.7,en;q=0.3 Connection: keep-alive Cookie: csrftoken=iRZDO5rsJzhh5peyyKhViN9yRslNQbuZ; Webstorm-713207de=ca4f5f1e-40e8-4bfd-97da-1be2f15f6e9e Referer: http://localhost:8888/mystream/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 2023/03/25 13:50:34 DEB [HLS] [conn 172.18.0.1] [s->c] HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: application/x-mpegURL Server: rtsp-simple-server (body of 122 bytes) 2023/03/25 13:50:36 DEB [HLS] [conn 172.18.0.1] GET /mystream/index.m3u8 2023/03/25 13:50:36 DEB [HLS] [conn 172.18.0.1] [c->s] GET /mystream/index.m3u8 HTTP/1.1 Host: localhost:8888 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: ru,en-US;q=0.7,en;q=0.3 Connection: keep-alive Cookie: csrftoken=iRZDO5rsJzhh5peyyKhViN9yRslNQbuZ; Webstorm-713207de=ca4f5f1e-40e8-4bfd-97da-1be2f15f6e9e Referer: http://localhost:8888/mystream/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 2023/03/25 13:50:36 DEB [HLS] [conn 172.18.0.1] [s->c] HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: application/x-mpegURL Server: rtsp-simple-server (body of 122 bytes)
如何让Python生成的流在Firefox网页上正常显示?
解决方案
1. 调整FFmpeg参数,优化HLS兼容性
Firefox对HLS的兼容性要求更严格,尤其是关键帧、封装格式的处理。修改FFmpeg命令参数:
- 添加
-movflags frag_keyframe+empty_moov:确保输出流碎片化,适配实时HLS播放 - 调整关键帧间隔:将
-force_key_frames expr:eq(mod(n,3),0)改为-g 2(每2帧一个关键帧,匹配低帧率场景)
修改后的Python中FFmpeg命令部分:
cmd = shlex.split( f'ffmpeg' f' -y' f' -f rawvideo' f' -vcodec rawvideo' f' -s {width}x{height}' f' -pix_fmt bgr24' f' -r {framerate}' f' -i -' f' -r {framerate}' f' -g 2' f' -vcodec libx264' f' -crf 18' f' -preset ultrafast' f' -tune zerolatency' f' -movflags frag_keyframe+empty_moov' f' -f rtsp' f' -rtsp_transport tcp' f' rtsp://localhost:8554/mystream' )
2. 强制刷新FFmpeg输入缓冲区
Python写入数据后,缓冲区可能未及时刷新,导致FFmpeg无法处理帧。在write后添加flush操作:
ffmpeg_process.stdin.write(image.tobytes()) ffmpeg_process.stdin.flush() # 强制刷新缓冲区 time.sleep(frame_duration)
3. 优化rtsp-simple-server的HLS配置
在服务器配置文件中调整以下参数:
hlsSegmentCount: 5:保留更多历史片段,避免Firefox请求不到有效内容hlsSegmentDuration: 2:片段长度与关键帧间隔匹配
4. 测试中间封装成MP4(可选)
如果原始帧推送仍有问题,可先将帧封装为MP4再转RTSP,补充元数据:
cmd = shlex.split( f'ffmpeg' f' -y' f' -f rawvideo' f' -vcodec rawvideo' f' -s {width}x{height}' f' -pix_fmt bgr24' f' -r {framerate}' f' -i -' f' -r {framerate}' f' -g 2' f' -vcodec libx264' f' -crf 18' f' -preset ultrafast' f' -tune zerolatency' f' -movflags frag_keyframe+empty_moov+faststart' f' -f mp4 - | ffmpeg -y -i - -f rtsp -rtsp_transport tcp rtsp://localhost:8554/mystream' )
注意:此方式需启用shell=True(需注意安全风险),或调整subprocess的管道处理逻辑。
内容的提问来源于stack exchange,提问作者Powercoder
相关产品推荐
相关产品推荐

