基于node-media-server实现的http-flv转推流程序

    以前给网页展示的rtsp流,使用crtmpserver做了稍加改动后转推过去的,但随着flash的淘汰,videojs这个项目组也打算在这次升级中淘汰掉,改用flvjs。

    问题就是flvjs不支持rtmp,而要在crtmpserver上添加新的转流代码,一是实力不够,二是时间不够,于是选了一个成熟的http-flv框架,稍加修改。

    大概流程就会是,网页要看一个rtsp的流视频,按着约定构造一个http://serverIp:serverport/live/rtsp的base64编码.flv,

    例如:http://127.0.0.1:8000/live/cnRzcDovL2FkbWluOmFkbWluMTIzQDEwLjIuMy4xMDE=.flv

    这样,在转推流的server收到这个请求,会截取到这个base64,解码后调用ffmpeg做一个推流,推个rtmp到流回来。

    应为nodejs可以注册事件,而且可以在链接connect和disconnect的时候对ffmpeg的调用经行管理。

 1 const { globalAgent } = require('http');
 2 const NodeMediaServer  = require('node-media-server');
 3 const numCPUs = require('os').cpus().length;
 4 var HashMap = require('hashmap').HashMap;
 5 
 6 const config = {
 7   rtmp: {
 8     port: 1935,
 9     chunk_size: 60000,
10     gop_cache: true,
11     ping: 60,
12     ping_timeout: 30
13   },
14 
15   http: {
16     port: 8000,
17     allow_origin: '*'
18   },
19   cluster: {
20     num: numCPUs
21   }
22 }
23 
24 var nms = new NodeMediaServer(config)
25 nms.run();
26 
27 var pmap = new HashMap();
28 var cmap = new HashMap();
29 const exec = require('child_process').execFile;
30 
31 function strsub( str ) {
32   var list = str.split( "/" );
33   return list[2]
34 }
35 
36 nms.on('preConnect', (id, args)=>{
37   console.log('[NodeEvent on preConnect]', `id=${id} args=${JSON.stringify(args)}`);
38   jobj = JSON.stringify(args);
39   console.log(args['streamPath']);
40   if ( args['streamPath'] != undefined ) {
41     var base64 = strsub( args['streamPath']) ;
42     var tmp = new Buffer( base64, 'base64' );
43     var rtsp = tmp.toString();
44     console.log( base64, rtsp );
45     if ( cmap.has( base64 ) ) {
46       num = cmap.get( base64 );
47       num = num + 1;
48       cmap.set( base64, num );
49     } else {
50       pro = exec( "ffmpeg.exe", ["-rtsp_transport", "tcp", "-i", rtsp, "-vcodec", "copy", "-acodec", "aac", "-f", "flv", "rtmp://127.0.0.1" + args['streamPath'] ],function(err,stdout,stderr){
51         if(err){
52             console.error(err);
53         }
54       });
55       cmap.set( base64, 1 );
56       pmap.set( base64, pro.pid );
57     }
58   }
59 });
60 
61 nms.on('doneConnect', (id, args) => {
62   console.log('[NodeEvent on doneConnect]', `id=${id} args=${JSON.stringify(args)}`);
63   if ( args['streamPath'] != undefined ) {
64     var base64 = strsub( args['streamPath']) ;
65     console.log( base64 );
66     if ( cmap.has( base64 ) ) {
67       num = cmap.get( base64 );
68       pro = pmap.get( base64 );
69       num -= 1;
70       cmap.set( base64, num );
71       console.log( num, pro );
72       if ( num == 0 ) {
73         exec( "taskkill", [ "/F", "/PID", pro ] );
74         cmap.remove( base64 );
75         pmap.remove( base64 );
76       }
77     }
78   }
79 });

 

posted on 2021-06-08 16:34  LLawliet  阅读(925)  评论(0编辑  收藏  举报

导航