您当前的位置:首页 > 计算机 > 服务器 > 网络服务

ffmpeg实现rtsp转rtmp

时间:01-31来源:作者:点击数:

首先,说一下ffmpeg实现rtsp转rtmp需要的条件:

(1)ffmpeg包:https://github.com/xueying123-cat/ffmpeg

(2)nginx-rtmp:https://github.com/xueying123-cat/nginx-rtmp.git

(3)转码服务,https://github.com/xueying123-cat/camera.git,这个代码对于多个转流同时执行可能存在线程不能正常结束的问题,大家有好的建议可以留言赐教

思路:转码服务将SVR中的rtsp流通过ffmpeg包转化为rtmp包,然后nginx-rtmp支持rtmp流播放。

ffmpeg转流命令:

ffmpeg -re  -rtsp_transport tcp -i "rtsp://username:password@serverIp/id=chnid" -f flv -vcodec copy -acodec copy -f flv -s 1280x720 -q 10 "rtmp://nginx_rtmp_ip:nginx_rtmp_ip/live/test"

nginx-rtmp的nginx-conf配置:

worker_processes  1;

error_log  logs/error.log info;

events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1935;
        chunk_size 4096;   #//数据传输块的大小
        application live {
            live on;
        }
		application vod {
            play D:\lib; #//视频文件存放位置。
        }
        application hls {
            live on;
            hls on;  
            hls_path D:\lib;  
            hls_fragment 8s;  
        }
    }
}

http {
    server {
        listen      8083;
		···
    }
}

现在说一下转码服务如何实现将rtsp流转化为rtmp流

//(1)获取当前转流命令,配置在常量类里
String command = ffmpegCommand.RTSP_TO_RTMP.getValue()
        .replace("rtspUrl", rtsp)
        .replace("rtmpUrl", rtmp);

//(2)执行cmd转流命令
Runtime.getRuntime().exec(commond)

//(3)将当前转流功能线程里执行,维护当前转流功能不被其他请求打扰
private static ThreadLocal<BufferedReader> br = ThreadLocal.<BufferedReader>withInitial(() -> null);
private static ThreadLocal<String> threadId = ThreadLocal.<String>withInitial(() -> null);    //定义线程内变量
private static ThreadLocal<Boolean> cameraStatus = ThreadLocal.<Boolean>withInitial(() -> false);

//在本机创建一个进程
Process process = Runtime.getRuntime().exec(command);

new Thread(() -> {
    cameraStatus.set(true);
    InputStream is = process.getErrorStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    br.set(reader);
    threadId.set(id);

    while (cameraStatus.get()) {
        //对流操作
        ···
        
        if (Thread.currentThread().isInterrupted()) {
            cameraStatus.set(false);
            closeResources(is, reader);
        }
    }

}
//(4)结束转流时,中断线程,并向当前线程中发送ffmpeg的停止命令q指令终止process的进程,停止当前线程
    thread.interrupt();
    OutputStream out = process.getOutputStream();
    Writer w = new OutputStreamWriter(out);
    try {
        w.write("q");
        w.flush();
    } catch (IOException e) {
        throw new CameraException("IOException==stop=>", e.getMessage());
    } finally {
        try {
            if (w != null) {
                w.close();
            }
        } catch (IOException e) {
            throw new CameraException("IOException==closew=>", e.getMessage());
        }
    }

测试结果:

图像:

写的比较粗糙,如果哪里有不明白,欢迎留言

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门