Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
李勇
/
McuClient
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
李勇
8 years ago
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
a7a75ace3469c14b5f27898b5f3e650699c76fe9
a7a75ace
1 parent
9dcfe2cc
1.修改FLASH推流拉流的规则-使用腾讯云
隐藏空白字符变更
内嵌
并排对比
正在显示
9 个修改的文件
包含
325 行增加
和
62 行删除
doc/nodeJs调用接口数据.txt
doc/录制.txt
doc/日志上传.txt
doc/腾讯云视频录制回调数据结构.txt
src/EngineEntrance.js
src/GlobalConfig.js
src/RecordPlayBackParse.js
src/SystemConfig.js
src/apes/MediaModule.js
doc/nodeJs调用接口数据.txt
0 → 100644
查看文件 @
a7a75ac
1.开启录制(开始推流)共用一个接口
{
"appId": "xxxxxxx",
"channel": "xxxxx_xxxx",
"channelKey": "xxxxxx",
"uid": 11111,
"userId": "xxx",
"userName": "xxx",
"userRole": "xxx",
"timestamp": "发送消息的的客户端时间戳",
"recordTimestamp": "当前录制进行的时间戳(回放时使用)"
}
2.停止推流
{
"appId": "xxxxxxx",
"channel": "xxxxx_xxxx",
"channelKey": "xxxxxx",
"uid": 11111,
"userId": "xxx",
"userName": "xxx",
"userRole": "xxx",
"timestamp": "发送消息的的客户端时间戳",
"recordTimestamp": "当前录制进行的时间戳(回放时使用)"
}
3.停止录制
{
"appId": "xxxxxxx",
"channel": "xxxxx_xxxx",
"channelKey": "xxxxxx",
"uid": 11111,
"userId": "xxx",
"userName": "xxx",
"userRole": "xxx",
"timestamp": "发送消息的的客户端时间戳",
"recordTimestamp": "当前录制进行的时间戳(回放时使用)"
}
\ No newline at end of file
...
...
doc/录制.txt
0 → 100644
查看文件 @
a7a75ac
1.时间戳 recordTimestamp
2.开始录制 startRecord
3.停止录制 stopRecord
4.录制权限 :
A.第一个进入课堂的人开启录制;
B.老师或最后一个离开课堂的人停止录制(课堂中没有人的时候10分钟后会停止录制)
C.课堂录制时间更新:老师->1个人->多个人且没有老师的时候,按nodeId值最小的人来更新(人员离开或更新的时候需要选择一个人)
5.课堂进行时间单独更新,和之前的逻辑一致,暂停和未开始的时候不记录;
6.录制的时间更新只要开启录制之后就更新,10秒一次发送到Saas和MCU同步;
7.刚进入的人员的录制时间从Saas获取默认的,MCU同步更新的时候更改为最新时间;
8.计时器:
updateTimer(){
//1.更新课堂时间,课堂开始上课的情况下更新
//2.更新录制时间,开启录制的情况下更新
}
\ No newline at end of file
...
...
doc/日志上传.txt
0 → 100644
查看文件 @
a7a75ac
type 1(error) 2(warning) 3(info)
classId
userId
nodeId
data:'aaa\nbbb'
//sdk定义好消息格式,多个消息用换行符 \n隔开
20170729 16:42:00 INFO XX.js receive param name=lipeng
...
...
doc/腾讯云视频录制回调数据结构.txt
0 → 100644
查看文件 @
a7a75ac
[
{
"app": "txlivepush.xuedianyun.com ",
"appid": 1251457656,
"appname": "live",
"channel_id": "marketflashtest_1966232762_user_627052_983041_1506308668",
"errcode": 0,
"errmsg": "Maybe Error return Data no record!",
"event_time": 1506308670,
"event_type": 1,
"idc_id": 34,
"node": "125.39.15.21",
"sequence": "7037777160241646428",
"set_id": 2,
"sign": "2eb0dcbd2ac7c3bade3089bb9aa999be",
"stream_id": "marketflashtest_1966232762_user_627052_983041_1506308668",
"stream_param": "bizid=11220&txSecret=339c4094afe1ae427e7bcd7f1f8d1128&txTime=59c91afc&record=hls&record_interval=5400",
"t": 1506309271,
"user_ip": "61.135.194.200"
},
{
"appid": 1251457656,
"channel_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
"duration": 63,
"end_time": 1506308756,
"event_type": 100,
"file_format": "hls",
"file_id": "9031868223267109922",
"file_size": 1349,
"media_start_time": 2931,
"record_file_id": "9031868223267109922",
"sign": "21f73f7e75f9e75196d1b16a536eaff2",
"start_time": 1506308695,
"stream_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
"stream_param": "bizid=11220&txSecret=2a53a100442dbd5d660ff14edb4af853&txTime=59c91b10&record=hls&record_interval=5400",
"t": 1506309357,
"task_id": "479501701",
"video_id": "5158_e9a44513cce1471790f8b0c50c983ccc",
"video_url": "http://1251457656.vod2.myqcloud.com/9425a3e9vodgzp1251457656/6367ba459031868223267109922/playlist.m3u8 "
},
{
"app": "txlivepush.xuedianyun.com",
"appid": 1251457656,
"appname": "live",
"channel_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
"errcode": 2,
"errmsg": "recv rtmpcloseStream",
"event_time": 1506308756,
"event_type": 0,
"idc_id": 34,
"node": "125.39.15.21",
"sequence": "7037777160241957731",
"set_id": 2,
"sign": "21f73f7e75f9e75196d1b16a536eaff2",
"stream_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
"stream_param": "bizid=11220&txSecret=2a53a100442dbd5d660ff14edb4af853&txTime=59c91b10&record=hls&record_interval=5400",
"t": 1506309357,
"user_ip": "61.135.194.200"
}
]
\ No newline at end of file
...
...
src/EngineEntrance.js
查看文件 @
a7a75ac
...
...
@@ -62,7 +62,7 @@ export default class MessageEntrance extends Emiter {
constructor
()
{
super
();
//sdk 信息
GlobalConfig
.
sdkVersion
=
"v2.1
0.7.20170921
"
;
GlobalConfig
.
sdkVersion
=
"v2.1
1.13.20170925
"
;
loger
.
warn
(
"sdkVersion:"
+
GlobalConfig
.
sdkVersion
);
//设置
...
...
@@ -493,7 +493,7 @@ export default class MessageEntrance extends Emiter {
if
(
!
_data
){
return
;
}
if
(
GlobalConfig
.
deviceType
==
1
||
GlobalConfig
.
deviceType
==
2
||
_data
.
nodeId
==
GlobalConfig
.
nodeId
){
if
(
GlobalConfig
.
deviceType
==
1
||
GlobalConfig
.
deviceType
==
2
||
GlobalConfig
.
deviceType
==
3
||
_data
.
nodeId
==
GlobalConfig
.
nodeId
){
return
;
}
if
(
_webRtc
){
...
...
@@ -552,6 +552,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig
.
isRecordPlayBack
=
false
;
//设置为非录制回放状态
GlobalConfig
.
classId
=
parseInt
(
_param
.
classId
);
GlobalConfig
.
portal
=
_param
.
portal
||
""
;
GlobalConfig
.
openFlash
=
Boolean
(
_param
.
openFlash
);
if
(
GlobalConfig
.
isHttps
==
true
){
//https的时候替换所有80端口
GlobalConfig
.
portal
=
GlobalConfig
.
replacePort
(
GlobalConfig
.
portal
,
":80"
,
""
);
...
...
@@ -1292,10 +1293,12 @@ export default class MessageEntrance extends Emiter {
//加入课堂成功,广播消息
this
.
_emit
(
MessageTypes
.
CLASS_JOIN_SUCCESS
,
joinClassSuccessCallBackData
);
setTimeout
(()
=>
{
//加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
this
.
_joinChannel
({
channelId
:
GlobalConfig
.
channelId
,
channelKey
:
GlobalConfig
.
channelKey
,
uid
:
GlobalConfig
.
userUid
,
info
:
""
+
GlobalConfig
.
userRole
});
},
1000
);
if
(
GlobalConfig
.
appId
&&!
GlobalConfig
.
openFlash
){
setTimeout
(()
=>
{
//加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
this
.
_joinChannel
({
channelId
:
GlobalConfig
.
channelId
,
channelKey
:
GlobalConfig
.
channelKey
,
uid
:
GlobalConfig
.
userUid
,
info
:
""
+
GlobalConfig
.
userRole
});
},
1000
);
}
}
//切换MCU ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)
...
...
@@ -1889,14 +1892,22 @@ export default class MessageEntrance extends Emiter {
loger
.
warn
(
"开启录制回放流程失败->还未创建模块"
);
}
}
else
{
//初始化音视频通话sdk
this
.
_initWebRtcSdk
({
appId
:
GlobalConfig
.
appId
},()
=>
{
//音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
if
(
GlobalConfig
.
appId
&&!
GlobalConfig
.
openFlash
){
loger
.
log
(
"使用webRtc通话模式"
);
//加入webRtc
this
.
_initWebRtcSdk
({
appId
:
GlobalConfig
.
appId
},()
=>
{
//音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this
.
loadServerJsonAndgetUserIpInfo
();
});
}
else
{
//加入flash
loger
.
log
(
"使用flash通话模式"
);
this
.
loadServerJsonAndgetUserIpInfo
();
});
}
/*
//根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this.loadServerJsonAndgetUserIpInfo();
...
...
src/GlobalConfig.js
查看文件 @
a7a75ac
...
...
@@ -371,6 +371,19 @@ class GlobalConfig {
}
}
//通过IP查找IP对象
static
getIpItem
(
ip
,
ipList
){
if
(
!
ip
||!
ipList
)
{
return
null
;
}
for
(
let
i
=
0
;
i
<
ipList
.
length
;
i
++
){
let
item
=
ipList
[
i
];
if
(
item
&&
item
.
ip
==
ip
){
return
item
;
}
}
return
null
;
}
}
GlobalConfig
.
statusCode_0
=
{
"code"
:
0
,
message
:
"SDK 未初始化"
};
...
...
@@ -578,7 +591,7 @@ GlobalConfig.locationProtocol="http://";//https;或http:
GlobalConfig
.
websocketProtocol
=
"ws://"
;
//wss或ws
GlobalConfig
.
isHttps
=
false
;
//是否是https
GlobalConfig
.
openFlash
=
false
;
//使用flash通话模式。默认为false,使用的是webRtc
//webRtc
GlobalConfig
.
appId
=
''
;
GlobalConfig
.
appCertificate
=
""
;
...
...
src/RecordPlayBackParse.js
查看文件 @
a7a75ac
...
...
@@ -123,7 +123,6 @@ class RecordPlayBackParse extends Emiter {
//解析和储存,录制回放EverSocket底层消息处理 data-数据;timestamp-数据对应的时间戳
_parseSaveSocketMsgReceivedHandler
(
data
,
timestamp
)
{
let
pduMsg
=
pdu
.
decode_pdu
(
data
);
let
pduType
=
pduMsg
.
get
(
"type"
);
let
pduData
=
pduMsg
.
get
(
"data"
);
...
...
@@ -135,7 +134,7 @@ class RecordPlayBackParse extends Emiter {
pduMsg
.
type
=
PduType
.
RCPDU_SEND_DATA_REQUEST
;
pduType
=
PduType
.
RCPDU_SEND_DATA_REQUEST
;
}
loger
.
log
(
'解析和储存->pduType'
,
pduType
);
//
loger.log('解析和储存->pduType', pduType);
switch
(
pduType
)
{
case
PduType
.
RCPDU_CONNECT_PROVIDER_RESPONSE
:
//加入课堂请求返回数据处理
...
...
@@ -161,7 +160,7 @@ class RecordPlayBackParse extends Emiter {
let
ape
=
this
.
_apes
[
pduMsg
.
sessionId
];
let
sessionLabel
=
ApeConsts
(
pduMsg
.
sessionId
);
//只做解析存储,不对外发送
loger
.
log
(
'解析数据-timestamp->'
,
timestamp
,
'sessionId->'
,
pduMsg
.
sessionId
,
'sessionLabel->'
,
sessionLabel
,
"subType:"
+
pduMsg
.
subType
);
//
loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel,"subType:"+pduMsg.subType);
switch
(
pduMsg
.
sessionId
)
{
case
ApeConsts
.
CONFERENCE_SESSION_ID
:
this
.
saveParseData
(
data
,
timestamp
,
this
.
_conferApeMssages
);
...
...
@@ -183,11 +182,12 @@ class RecordPlayBackParse extends Emiter {
break
;
case
ApeConsts
.
VIDEO_SESSION_ID
:
this
.
saveParseData
(
data
,
timestamp
,
this
.
_videoApeMssages
);
this
.
unPackpduRegAdapterHandler
(
pduMsg
.
data
,
timestamp
,
data
,
ApeConsts
.
VIDEO_SESSION_ID
)
this
.
unpackVideoBroadcastMessage
(
pduMsg
,
timestamp
,
data
);
this
.
unPackpduRegAdapterHandler
(
pduMsg
.
data
,
timestamp
,
data
,
ApeConsts
.
VIDEO_SESSION_ID
,
pduMsg
.
subType
)
break
;
case
ApeConsts
.
AUDIO_SESSION_ID
:
this
.
saveParseData
(
data
,
timestamp
,
this
.
_audioApeMssages
);
this
.
unPackpduRegAdapterHandler
(
pduMsg
.
data
,
timestamp
,
data
,
ApeConsts
.
AUDIO_SESSION_ID
)
this
.
unPackpduRegAdapterHandler
(
pduMsg
.
data
,
timestamp
,
data
,
ApeConsts
.
AUDIO_SESSION_ID
,
pduMsg
.
subType
)
break
;
default
:
break
;
...
...
@@ -625,10 +625,62 @@ class RecordPlayBackParse extends Emiter {
}
}
}
//解析视频模块的广播消息
unpackVideoBroadcastMessage
(
pduMsg
,
timestamp
,
data
){
//console.log("VIDEO_SESSION_ID-pduMsg",pduMsg);
if
(
!
pduMsg
){
return
;
}
if
(
pduMsg
.
subType
!=
pdu
.
RCPDU_SEND_VIDEO_DATA_REQUEST
){
//视频广播消息,只处理501消息
return
;
}
try
{
let
videoReceivePdu
=
pdu
[
'RCVideoSendDataRequestPdu'
].
decode
(
pduMsg
.
data
);
if
(
videoReceivePdu
==
null
)
{
loger
.
warn
(
"视频模块广播消息-decode->失败"
);
return
;
}
videoReceivePdu
.
data
=
ArrayBufferUtil
.
uint8ArrayToStr
(
videoReceivePdu
.
data
,
2
);
//开头两个字会乱码
let
dataObj
=
{};
try
{
dataObj
=
JSON
.
parse
(
videoReceivePdu
.
data
);
}
catch
(
err
)
{
loger
.
warn
(
'视频模块广播消息->JSON转换失败'
);
dataObj
=
videoReceivePdu
.
data
;
}
videoReceivePdu
.
data
=
dataObj
;
//actionType:40
//data :Object
//fromNodeId :902994631
//toNodeId : 0
if
(
videoReceivePdu
.
actionType
==
40
){
if
(
!
this
.
_videoApeBroadcastMssages
[
videoReceivePdu
.
fromNodeId
]){
this
.
_videoApeBroadcastMssages
[
videoReceivePdu
.
fromNodeId
]
=
{};
}
/*
//结构
{
nodeId:{
时间戳:{数据}
},
nodeId:{
时间戳:{数据}
},.....
}*/
this
.
_videoApeBroadcastMssages
[
videoReceivePdu
.
fromNodeId
][
timestamp
]
=
{
parseData
:
videoReceivePdu
,
byteData
:
data
,
timestamp
:
timestamp
};
//this._videoApeBroadcastMssages[timestamp]={parseData:videoReceivePdu,byteData:data,timestamp: timestamp};
}
}
catch
(
err
){
console
.
log
(
"视频模块广播消息->解析失败"
,
err
.
message
);
}
}
//音视频的数据需要解析,然后按频道储存数据
// 解析pdu RCAdapterPdu的数据: regBuffer(RCAdapterPdu数据),timestamp(时间戳), data(mcu的原始数据) sessionId(类型)
unPackpduRegAdapterHandler
(
regBuffer
,
timestamp
,
data
,
sessionId
)
{
unPackpduRegAdapterHandler
(
regBuffer
,
timestamp
,
data
,
sessionId
,
subType
)
{
let
regPdu
;
let
regItems
;
let
regItemSize
;
...
...
@@ -639,13 +691,7 @@ class RecordPlayBackParse extends Emiter {
regItemSize
=
regItems
.
length
;
}
catch
(
err
){
console
.
warn
(
'RCAdapterPdu->unpack-error->type类型不对'
);
try
{
let
sendDataPdu
=
pdu
[
'RCVideoSendDataRequestPdu'
].
decode
(
regBuffer
);
console
.
log
(
"RCVideoSendDataRequestPdu"
,
sendDataPdu
);
}
catch
(
err
){
}
console
.
warn
(
'RCAdapterPdu->unpack-error->type类型不对'
,
"subType:"
+
subType
);
return
;
}
...
...
@@ -670,7 +716,8 @@ class RecordPlayBackParse extends Emiter {
let
sub_type
=
regUpdatedItem
.
subType
;
let
object_id
=
regUpdatedItem
.
objId
;
let
user_data
=
regUpdatedItem
.
userData
;
//console.log('RCRegistryUpdateObjPdu',regUpdatedItem)
console
.
log
(
'RCRegistryUpdateObjPdu'
,
regUpdatedItem
)
switch
(
sub_type
)
{
case
pdu
.
RCPDU_REG_ROSTER_INSERT_PDU
:
...
...
@@ -723,7 +770,7 @@ class RecordPlayBackParse extends Emiter {
loger
.
warn
(
"视频控制消息处理,收到的消息为null,不做处理"
);
return
;
}
videoReceivePdu
.
data
=
this
.
_rC
ArrayBufferUtil
.
uint8ArrayToStr
(
videoReceivePdu
.
data
,
2
);
//开头两个字会乱码
videoReceivePdu
.
data
=
ArrayBufferUtil
.
uint8ArrayToStr
(
videoReceivePdu
.
data
,
2
);
//开头两个字会乱码
let
dataObj
=
{};
try
{
dataObj
=
JSON
.
parse
(
videoReceivePdu
.
data
);
...
...
src/SystemConfig.js
查看文件 @
a7a75ac
...
...
@@ -52,28 +52,6 @@ class SystemConfig {
}
//获取浏览器和信息
/* static getBrowserInfo() {
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var re = /(trident|msie|firefox|chrome|opera|version).*?([\d.]+)/;
var m = ua.match(re);
if (!m) m = ["version/1.0.0", "version", "1.0.0"];
Sys.explorer = m[1].replace(/version/, "'safari");
//判断是否是IE11
if (Sys.explorer == "trident") {
Sys.explorer = "IE11"
Sys.explorerVersion = "11.0";
} else if (Sys.explorer == "msie") {
//IE
Sys.explorer = "IE"
Sys.explorerVersion = m[2];
} else {
//非IE
Sys.explorerVersion = m[2];
}
return Sys;
}*/
//获取浏览器和信息
static
getBrowserInfo
()
{
let
Sys
=
{};
Sys
.
explorer
=
"unknow"
;
...
...
@@ -83,7 +61,7 @@ class SystemConfig {
let
re
=
/
(
trident|msie|firefox|chrome|version
)
.*
?([\d
.
]
+
)
/
;
let
m
=
ua
.
match
(
re
);
if
(
!
m
)
m
=
[
"version/1.0.0"
,
"version"
,
"1.0.0"
];
Sys
.
explorer
=
m
[
1
].
replace
(
/version/
,
"
'
safari"
);
Sys
.
explorer
=
m
[
1
].
replace
(
/version/
,
"safari"
);
//判断是否是IE11
if
(
Sys
.
explorer
==
"trident"
)
{
Sys
.
explorer
=
"IE11"
...
...
src/apes/MediaModule.js
查看文件 @
a7a75ac
...
...
@@ -7,6 +7,7 @@ import Loger from 'Loger';
import
MessageTypes
from
'MessageTypes'
;
import
GlobalConfig
from
'GlobalConfig'
;
import
EngineUtils
from
'EngineUtils'
;
import
MD5
from
"md5"
;
let
loger
=
Loger
.
getLoger
(
'MediaModule'
);
...
...
@@ -37,22 +38,36 @@ class MediaModule {
if
(
!
GlobalConfig
.
MS_PLAY_HLS_IP
)
{
loger
.
error
(
"HLS拉流地址地址无效"
);
}
//http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/index.m3u8
/*
//http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/index.m3u8
if (GlobalConfig.siteId == GlobalConfig.siteId_letv) {
//乐视的hls地址规则
fileName = 'desc.m3u8';
} else {
//fileName='index.m3u8';
fileName = 'playlist.m3u8';
}
}
*/
port
=
(
GlobalConfig
.
MS_PLAY_HLS_PORT
==
""
||
GlobalConfig
.
MS_PLAY_HLS_PORT
==
null
)
?
""
:
":"
+
GlobalConfig
.
MS_PLAY_HLS_PORT
;
//path = "http://" + GlobalConfig.MS_PLAY_HLS_IP
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
MS_PLAY_HLS_IP
,
GlobalConfig
.
hlsPullListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
let
hlsSuffix
=
"/playlist.m3u8"
;
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
hlsSuffix
=
ipItem
.
hlsSuffix
||
"/playlist.m3u8"
;
}
path
=
GlobalConfig
.
locationProtocol
+
GlobalConfig
.
MS_PLAY_HLS_IP
+
port
+
"/"
+
type
+
"/"
+
_param
.
streamId
+
hlsSuffix
;
//
//+ "/"+fileName;//
/*path =GlobalConfig.locationProtocol + GlobalConfig.MS_PLAY_HLS_IP
+ port + "/live/"
+ _param.streamId
+ ".m3u8";//
//+ "/"+fileName;//
*/
}
else
{
//RTMP
...
...
@@ -60,12 +75,20 @@ class MediaModule {
loger
.
error
(
"RTMP拉流地址地址无效"
);
}
port
=
(
GlobalConfig
.
MS_PLAY_RTMP_PORT
==
""
||
GlobalConfig
.
MS_PLAY_RTMP_PORT
==
null
)
?
""
:
":"
+
GlobalConfig
.
MS_PLAY_RTMP_PORT
;
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
MS_PLAY_RTMP_IP
,
GlobalConfig
.
rtmpPullListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
}
path
=
"rtmp://"
+
GlobalConfig
.
MS_PLAY_RTMP_IP
+
port
+
"/
live
/"
+
port
+
"/
"
+
type
+
"
/"
+
_param
.
streamId
;
}
//path = "rtmp://" + GlobalConfig.MS_PLAY_RTMP_IP
// + port + "/live/"
// + _param.streamId;
}
path
=
path
.
replace
(
"::"
,
":"
);
//如果ip和port之间有多的:需要去掉
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
""
,
"playUrl"
:
path
};
}
...
...
@@ -81,15 +104,41 @@ class MediaModule {
//M3U8 http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/total.m3u8
let
port
=
(
GlobalConfig
.
RS_RECORD_PLAY_PORT
==
""
||
GlobalConfig
.
RS_RECORD_PLAY_PORT
==
null
)
?
""
:
":"
+
GlobalConfig
.
RS_RECORD_PLAY_PORT
;
//let path = "http://" + GlobalConfig.RS_RECORD_PLAY_IP
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
RS_RECORD_PLAY_IP
,
GlobalConfig
.
rsPullListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
let
rHlsSuffix
=
"/total.m3u8"
;
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
rHlsSuffix
=
ipItem
.
rHlsSuffix
||
"/total.m3u8"
;
}
let
path
=
GlobalConfig
.
locationProtocol
+
GlobalConfig
.
RS_RECORD_PLAY_IP
+
port
+
"/
live
/"
+
port
+
"/
"
+
type
+
"
/"
+
_param
.
streamId
+
"/total.m3u8"
;
+
rHlsSuffix
;
path
=
path
.
replace
(
"::"
,
":"
);
//如果ip和port之间有多的:需要去掉
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
""
,
"playUrl"
:
path
};
}
//推流地址后缀拼接参数
setPublishSuffix
(
url
,
publishSuffix
,
streamId
){
let
newUrl
=
url
;
if
(
!
url
||!
publishSuffix
){
return
newUrl
;
}
//publishSuffix就是外部传入的key
//txSecret = MD5(key + stream+txTime)
let
txTime
=
new
Date
().
getTime
()
/
1000
+
(
12
*
60
*
60
);
//过去时间精确到分钟,转为16进制
txTime
=
parseInt
(
txTime
);
txTime
=
txTime
.
toString
(
16
);
let
txSecret
=
MD5
(
publishSuffix
+
streamId
+
txTime
);
//rtmp://11220.livepush.myqcloud.com/live/11220_c5a1ea0bce?bizid=11220&txSecret=b1d8af72bf62366eef31cbb5dc5c8778&txTime=59C5337F
newUrl
=
url
+
"?bizid=11220&txSecret="
+
txSecret
+
"&txTime="
+
txTime
+
"&record=hls&record_interval=5400"
;
loger
.
log
(
"生成的推流地址->"
+
newUrl
);
return
newUrl
;
}
//获取推流地址
getMediaPublishPath
(
_param
)
{
loger
.
log
(
'获取推流地址->'
);
...
...
@@ -116,8 +165,21 @@ class MediaModule {
+
"_"
+
freeChannel
+
"_"
+
timestamp
;
//生成推流地址和推流数据(同步数据的时候用)
//let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
// + port + "/" + pubType + "/" + streamId;
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
MS_PUBLISH_IP
,
GlobalConfig
.
msListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
}
let
publishUrl
=
"rtmp://"
+
GlobalConfig
.
MS_PUBLISH_IP
+
port
+
"/"
+
pubType
+
"/"
+
streamId
;
+
port
+
"/"
+
type
+
"/"
+
streamId
;
//设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
if
(
ipItem
&&
ipItem
.
publishSuffix
){
publishUrl
=
this
.
setPublishSuffix
(
publishUrl
,
ipItem
.
publishSuffix
,
streamId
);
}
publishUrl
=
publishUrl
.
replace
(
"::"
,
":"
);
//如果ip和port之间有多的:需要去掉
this
.
needPublishMediaChannel
[
publishUrl
]
=
{
...
...
@@ -169,9 +231,21 @@ class MediaModule {
+
"_"
+
freeChannel
+
"_"
+
timestamp
;
//生成推流地址和推流数据(同步数据的时候用)
//let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
// + port + "/" + pubType + "/" + streamId;
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
MS_PUBLISH_IP
,
GlobalConfig
.
msListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
}
let
publishUrl
=
"rtmp://"
+
GlobalConfig
.
MS_PUBLISH_IP
+
port
+
"/"
+
pubT
ype
+
"/"
+
streamId
;
+
port
+
"/"
+
t
ype
+
"/"
+
streamId
;
//设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
if
(
ipItem
&&
ipItem
.
publishSuffix
){
publishUrl
=
this
.
setPublishSuffix
(
publishUrl
,
ipItem
.
publishSuffix
,
streamId
);
}
publishUrl
=
publishUrl
.
replace
(
"::"
,
":"
);
//如果ip和port之间有多的:需要去掉
this
.
needPublishMediaChannel
[
publishUrl
]
=
{
"channelId"
:
freeChannel
,
...
...
@@ -213,8 +287,20 @@ class MediaModule {
+
"_"
+
shareChannel
+
"_"
+
timestamp
;
//生成推流地址和推流数据(同步数据的时候用)
//let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
// + port + "/" + pubType + "/" + streamId;
let
ipItem
=
GlobalConfig
.
getIpItem
(
GlobalConfig
.
MS_PUBLISH_IP
,
GlobalConfig
.
msListFinal
);
//获取IP对象
let
type
=
"live"
;
//默认值
if
(
ipItem
){
type
=
ipItem
.
type
||
"live"
;
}
let
publishUrl
=
"rtmp://"
+
GlobalConfig
.
MS_PUBLISH_IP
+
port
+
"/"
+
pubType
+
"/"
+
streamId
;
+
port
+
"/"
+
type
+
"/"
+
streamId
;
//设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
if
(
ipItem
&&
ipItem
.
publishSuffix
){
publishUrl
=
this
.
setPublishSuffix
(
publishUrl
,
ipItem
.
publishSuffix
,
streamId
);
}
publishUrl
=
publishUrl
.
replace
(
"::"
,
":"
);
//如果ip和port之间有多的:需要去掉
/* this.needPublishMediaChannel[publishUrl]={
...
...
请
注册
或
登录
后发表评论