被java调用shell进程,进程僵死搞郁闷了

别问我为什么要用java调用ffmpeg处理视频。主要是需要按需压缩,按需压缩。

1.为什么要压缩?

有几百路摄像头,摄像头的数据都是高清分辨率,达到了惊人的4096x2160,帧分辨率25。需要在页面同时展示4路,每路4m,一个页面需要同时占用16m。

其次客户端播放窗口只有400像素,通过客户端压缩,页面非常卡顿,一顿一顿的。

为什么使用ffmpeg压缩,ffmpeg是c++写的相对来说效率高,而且支持拉流。

于是想到的方法是按需压缩。

之前只有8路摄像头, 方案简单粗暴, 服务器实时拉流,处理后放在服务器等待客户端播放。但是大部分时间,浏览器不需要看摄像头,偶尔看一下,虽然是内网处理,但是仍然浪费了服务器资源和带宽。

最进突然要接入几百路摄像头,于是想到了按需压缩。打开摄像头看视频的时候再拉流压缩。

按需压缩就是等浏览器像服务器发起请求的时候,再拉流压缩。考虑到源摄像头有可能是坏的,第一次返回404给客户端。客户端发起重试,返回压流后的流媒体。

调研了前端播放器 videojs,支持重试,于是服务器开工。

服务器想到的使用java需要多线程处理。一个线程负责监控客户端播放请求,一个线程负责心跳检查。

程序逻辑很简单。 当有请求来的时候,调起拉流压流daemon,当然还需要溢出判断,统一服务器限制不能超过50路,50路服务器处理不过来,处理视频太耗资源了。还有就是锁机制,存在n多客户端,同时播放的需求,实际只需要压缩1路即可,其他客户端共用这一路,用memcached或者redis 解决这些很简单。对于架构来说,越简单,越可靠,为此引入memcached或者redis个人觉得性能和维护成本 ,都不值得,于是就在java程序里面实现了。

另外一个心跳检查,就是检查上面那个线程的数据,超过一定时间关闭拉流压缩,节省服务器资源。

    代码写好后,一切都按照预想的成果,开心而又愉快的运行。为了避免手工操作,写了一个定时脚本,监控并启动 这个java程序,昨天晚上启动,今天早上到公司一看,芭比Q了,java程序在运行,视频播放不出来。。。。 

       杀掉进程在xshell里面启动java 程序,播放正常。  但是通过crond 自动启动脚本,大约过2分钟,某一路视频无法播放。以为是心跳检查程序把 进程杀掉了。

        然后又重写代码,把进程和超时队列单独分开,也没有解决,又重新封装线程,还是这样。

在xshell里面为什么正常,很奇怪。 于是写了一个简单的daemon 程序,发现正常了。唯一的区别就是 ffmpeg 执行的时候,会输出很多消息,而且java调用c++程序,c++不能挂在后台,我强制在ffmpeg程序后面加& ,ffmpeg 被java终止了。

       找到问题就好解决了,把ffmpeg放在sh脚本里面,通过shell脚本把所有的输出 输出到null终端,ffmpeg */hls/aa >/dev/null 2>&1

    原因就是:  输出流会阻塞进程执行。

     Java进程执行有一个输入流,两个输出流(相对于外部程序)。当两个输出流有内容输出,而Java执行程序没有及时清空输出流时就会阻塞进程。

 java下是通过下面的方式调用的。

    被java调用shell进程,进程僵死搞郁闷了_第1张图片

      今天晚上,再跑一个晚上,希望程序正常,程序正常,还需要播放器封装,还需要部署流媒体服务器和压流的代码 脚本和文档。

     今天晚上,跑一个晚上,明天不正常,估计五一都没法安心的过了。经过改造后,不会因为网络播放卡,消耗带宽高,视频不清晰(浏览器压缩导致),播放不流畅了,也不会因为网络中断,导致延时过大了。

    单路从4m压缩到了400k,带宽缩小10倍,希望正常,不然劳动白费,也对不起我掉的头发啊。

      

你可能感兴趣的:(程序设计,java,ffmpeg,监控,直播,点播)