当对等端断开连接时,ffmpeg rtsp 服务器不会停止

当对等端断开连接时,ffmpeg rtsp 服务器不会停止

有一个 ffmpeg 实例在 VPS 上作为服务器运行,它将 RTSP 视频转换为 HLS 并将其提供给网络(使用 Apache)。RTSP 视频来自其他地方的计算机(在本例中是另一个城镇),我有一个 IP 摄像头连接到该计算机。计算机从 IP 摄像头获取 RTSP 数据并将其重新转换到 VPS。

这是我在那台计算机(我可以说是重新流式传输器)上使用的 ffmpeg 命令:

ffmpeg \
-rtsp_transport tcp \
-i rtsp://[IP address of the camera]:554/live \
-c:v copy \
-f rtsp \
-rtsp_transport tcp \
rtsp://[IP address of the VPS]:4445/live.sdp

这是我在 VPS 上使用的命令:

ffmpeg \
-rtsp_flags listen \
-listen_timeout 5 \
-timeout 5000000 \
-rtsp_transport tcp \
-i rtsp://[ip address of the VPS]:4445/live.sdp \
-map 0 \
-flags +global_header \
-fflags +igndts \
-c:v copy \
-g 0 \
-b:v 125k \
-maxrate 250k \
-bufsize 500k \
-hls_time 1 \
-hls_list_size 15 \
-hls_wrap 15 \
-y /dev/shm/hls/video.m3u8

到目前为止,一切都运行良好:我可以在浏览器中读取 HLS 流,而且它非常稳定和快速。当重新流化器和 VPS 之间的连接断开时,问题就出现了:我必须通过 ssh 进入 VPS 并手动重新启动 ffmpeg 实例。当地址-i(在 VPS 端)没有输入时,是否可以告诉 ffmpeg“崩溃”(或只是停止其进程)?我正在使用一个可以自动重新启动进程的 bash 脚本,所以这已经解决了。

为了避免混淆:根据ffmpeg 的官方文档timeout标志以 MICROSECONDS 作为值,并listen_timeout以 SECONDS 为单位。我见过很多人在争论这个话题 :)

答案1

希望我没有迟到。我通过监控 CPU 使用率解决了类似的问题。在我的例子中,当摄像机重新启动或连接断开时,FFMPEG 继续运行,但 CPU 使用率降至 0.0%。我使用 python 来监控它。以下是重要部分:

import subprocess, psutil
import time, os

# Run ffmpeg command
base_process = subprocess.Popen([
    'ffmpeg',
    '-rtsp_transport', 'tcp',
    '-i', LINK_RTSP,    
    '-map', '0:v', '-map', '0:a', '-vcodec', 'copy', '-acodec', 'aac', '-t', 60,
    os.path.expanduser(f'~/Desktop/{date}.mp4')        
])  

#Check process by CPU usage
control_process = psutil.Process(base_process.pid)
attempts = 5 #Sleep is 1 second, so if ffmpeg is not using cpu for 5 seconds, kill the process
while base_process.poll() is None:
    cpu_percent = control_process.cpu_percent()

    if cpu_percent == 0.0:
        attempts -= 1

    if attempts == 0:
        logger.info("ffmpeg is hanging (CPU usage is 0%). Killing the process!")
        while base_process.poll() is None:
            base_process.terminate()
            time.sleep(1)

        logger.info(f"Files to be recoved: {date}.mp4")
        try:
            for camera in connected_cameras.keys():
                os.rename(os.path.expanduser(f'{BASE_FOLDER}{camera}/{date}.mp4'), os.path.expanduser(f'{BASE_FOLDER}{camera}/{date}_recovery-needed.mp4'))
        except:
            pass
        
        break

    time.sleep(1)

我希望它有帮助。

相关内容