WebSocket播放视频是结合MediaSource的
总结:通过WebSocket获取视频流,提供给MediaSource,MediaSource结合video标签,播放视频。
这一套完全就是基于浏览器支持MediaSourceExtension(MSE)的,而我最终的目的是在unity3d里面播放视频,加入uinty3d不支持MediaSource和video标签,怎么折腾都没用。可能最后还会变成在uinty里面调要能够网页上的video来播放视频,调整一下窗口的大小。
在AppStore里面找了一下,没找到合适的资料,有个Embedded Browser说是完全支持HTML5包括视频,但是它的平台是windows,ios,linux,其实就是一个浏览器嵌入到unity程序中,没有webgl,而webgl其实就在浏览器里面了。这个在淘宝上有,3.0还买到35或者80。
接下来三个方向 1.WebRTC 2.Unity调用浏览器 3.解码播放
参考:MediaSource
1.理解并修改h5splayer.js
将文件和github上面的h5media.js以及h5sevent.js比较,将混淆后的变量名和方法名还原回去
function H5sPlayerWS(conf) {
var s;
this.sourceBuffer, this.buffer = [], this._mediaSource, this.video, this.wsSocket, this.checkSourceBufferTimerId, this.keepAliveTimerId, this.h = 0, this.l = 0,
this.u = 0, this.S = false, this.v = false, this.p = false, this.strCodec, this._conf = conf, console.log("Websocket Conf:",
conf), this._videoId = conf.videoid, this._pbconf = conf.pbconf, this._token = conf.token, void 0 === this._videoId ? (this._videoElemet = conf.videodom,
console.log(conf.token, "use dom directly")) : (this._videoElemet = document.getElementById(this._videoId), console.log(conf.token,
"use videoid")), this.video = this._videoElemet, null != this._pbconf && "false" == this._pbconf.showposter || (s = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session,
console.log(conf.token, "connect src"), this._videoElemet.setAttribute("poster", s))
}
function H5sPlayerRTC(conf) {
var s;
this.wsSocket, this.checkSourceBufferTimerId, this.keepAliveTimerId, this.h = 0, this.l = 0, this.u = 0, this.S = false, this.v = false, this._conf = conf,
this._videoId = conf.videoid, this._pbconf = conf.pbconf, this._token = conf.token, void 0 === this._videoId ? (this._videoElemet = conf.videodom,
console.log(conf.token, "use dom directly")) : (this._videoElemet = document.getElementById(this._videoId), console.log(conf.token,
"use videoid")), this.video = this._videoElemet, this.R = null, this.I = {
optional: [{
DtlsSrtpKeyAgreement: true
}]
},
this.A = {
mandatory: {
offerToReceiveAudio: true, offerToReceiveVideo: true
}
},
this.T = {
M: []
},
this.O = [], null != this._pbconf && "false" == this._pbconf.showposter || (s = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session,
console.log("connect src", conf.token), this._videoElemet.setAttribute("poster", s))
}
function createRTCSessionDescription(t) {
return console.log("createRTCSessionDescription "), new RTCSessionDescription(t)
}
function H5sPlayerHls(t) {
this.wsSocket, this.keepAliveTimerId, this._conf = t, this._videoId = t.videoid, this._token = t.token, this.J, this.N = t.hlsver, void 0 === this._videoId ? (this._videoElemet = t.videodom,
console.log(t.token, "use dom directly")) : (this._videoElemet = document.getElementById(this._videoId), console.log(t.token,
"use videoid")), this.g = this._videoElemet, this.g.type = "application/x-mpegURL", this.B = 0, this.U = 0;
var s = this._conf.protocol + "//" + window.location.host + "/api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session;
this._videoElemet.setAttribute("poster", s)
}
function H5sPlayerAudio(t) {
this.buffer = [], this.wsSocket, this.S = false, this.v = false, this._conf = t, console.log("Aduio Player Conf:",
t), this._token = t.token, this._ = new AudioContext
}
function H5sPlayerAudBack(t) {
this.buffer = [], this.wsSocket, this.S = false, this.v = false, this._conf = t, this.L = 0, this.D = 48e3, this.G = false,
console.log("Aduio Back Conf:", t), this._token = t.token, this._ = new AudioContext, console.log("sampleRate",
this._.sampleRate), this.K()
}
function float32ToInt16(t) {
for (var s = t.length, e = new Int16Array(s); s--;) {
e[s] = 32767 * Math.min(1, t[s]);
}
return e
}
H5sPlayerWS.prototype.reconnectFunction = function () {
console.error('reconnectFunction'+new Date());
true === this.S && (console.log("Reconnect..."), this.setupWebSocket(this._token), this.S = false)
},
H5sPlayerWS.prototype.getWebSocket = function (url) {
console.log('>> H5sPlayerWS.prototype.getWebSocket');
var ws;
try {
"http:" == this._conf.protocol && (ws = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + url) : new WebSocket("ws://" + this._conf.host + url)),
"https:" == this._conf.protocol && (console.log(this._conf.host), ws = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + url) : new WebSocket("wss://" + this._conf.host + url)),
console.log(this._conf.host)
}
catch (err) {
return void alert("error")
}
return ws;
},
H5sPlayerWS.prototype.readFromBuffer = function () {
//console.error('F');
//console.log(this.sourceBuffer);
if (null !== this.sourceBuffer && void 0 !== this.sourceBuffer) {
if (0 !== this.buffer.length && !this.sourceBuffer.updating) {
try {
var first = this.buffer.shift(), buff = new Uint8Array(first);
this.sourceBuffer.appendBuffer(buff)
}
catch (err) {
console.log(err)
}
}
}
else {
console.log(this.sourceBuffer, "is null or undefined");
}
//console.log(this.sourceBuffer);
},
H5sPlayerWS.prototype.keepAlive = function () {
//console.error('X keepaliveTimer');
//console.log(this);
//console.log(this.wsSocket);
try {
var t = {
cmd: "H5_KEEPALIVE"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
//获取websocket数据
H5sPlayerWS.prototype.onReceived = function (msg) {
//console.log('>> H5sPlayerWS.prototype.onReceived');
//console.log(msg.data);
//var ttt=String.fromCharCode.apply(null, new Uint8Array(msg.data));
//console.log(ttt);
return msg.data, ArrayBuffer, "string" == typeof msg.data ? (console.log("string"), void (null != this._pbconf && null != this._pbconf.callback && this._pbconf.callback(msg.data,
this._pbconf.userdata))) : true !== this.v ? false === this.p ? (this.strCodec = String.fromCharCode.apply(null, new Uint8Array(msg.data)),
this.initMediaSource(this), void (this.p = true)) : (this.buffer.push(msg.data), void this.readFromBuffer()) : void 0;
},
H5sPlayerWS.prototype.initMediaSource = function (player) {
console.log('initMediaSource');
try {
window.MediaSource = window.MediaSource || window.WebKitMediaSource, window.MediaSource || console.log("MediaSource API is not available");
var codec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
"MediaSource" in window && MediaSource.isTypeSupported(codec) ? console.log("MIME type or codec: ",
codec) : console.log("Unsupported MIME type or codec: ", codec), player._mediaSource = new window.MediaSource, player.video.autoplay = true,
console.log(player._videoId);
player.video.src = window.URL.createObjectURL(player._mediaSource), player.video.play(), player._mediaSource.addEventListener("sourceopen",
player.onMediaSourceOpen.bind(player), false)
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.onMediaSourceOpen = function () {
console.log("Add SourceBuffer"), this.sourceBuffer = this._mediaSource.addSourceBuffer(this.strCodec), this._mediaSource.duration = 1 / 0,
this._mediaSource.removeEventListener("sourceopen", this.onMediaSourceOpen, false), this.sourceBuffer.addEventListener("updateend",
this.readFromBuffer.bind(this), false);
},
H5sPlayerWS.prototype.setupWebSocket = function (token) {
console.log('>> H5sPlayerWS.prototype.setupWebSocket');
this.video.autoplay = true;
var url = "api/v1/h5swsapi", prof = "main";
if (void 0 === this._conf.streamprofile || (prof = this._conf.streamprofile), void 0 === this._pbconf) {
url = this._conf.rootpath + url + "?token=" + token + "&profile=" + prof + "&session=" + this._conf.session;
}
else {
var i = "false", o = "fake";
void 0 === this._pbconf.serverpb || (i = this._pbconf.serverpb), void 0 === this._pbconf.filename || (o = this._pbconf.filename),
url = this._conf.rootpath + url + "?token=" + token + "&playback=true&profile=" + prof + "&serverpb=" + i + "&begintime=" + encodeURIComponent(this._pbconf.begintime) + "&endtime=" + encodeURIComponent(this._pbconf.endtime) + "&filename=" + o + "&session=" + this._conf.session
}
this._conf.session, console.log(url), this.wsSocket = this.getWebSocket(url), console.log("setupWebSocket", this.wsSocket), this.wsSocket.binaryType = "arraybuffer",
(this.wsSocket._player = this).wsSocket.onmessage = this.onReceived.bind(this), this.wsSocket.onopen = function () {
console.log("wsSocket.onopen", this._player), this._player.checkSourceBufferTimerId = setInterval(this._player.checkSourceBuffer.bind(this._player), 1e4),
this._player.keepAliveTimerId = setInterval(this._player.keepAlive.bind(this._player), 1e3), null != this._player._pbconf && "true" === this._player._pbconf.autoplay && this._player.start();
},
this.wsSocket.onclose = function () {
console.log("wsSocket.onclose", this._player), true === this._player.v ? console.log("wsSocket.onclose disconnect") : this._player.S = true,
this._player.cleanupSourceBuffer(this._player), this._player.cleanupWebSocket(this._player), this._player.strCodec = "", this._player.p = false;
}
},
H5sPlayerWS.prototype.cleanupSourceBuffer = function (player) {
console.log("Cleanup Source Buffer", player);
try {
player.sourceBuffer.removeEventListener("updateend", player.readFromBuffer, false), player.sourceBuffer.abort(), document.documentMode || /Edge/.test(navigator.userAgent) ? console.log("IE or EDGE!") : player._mediaSource.removeSourceBuffer(player.sourceBuffer),
player.sourceBuffer = null, player._mediaSource = null, player.buffer = []
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.cleanupWebSocket = function (player) {
console.log("CleanupWebSocket", player);
//console.error(player);
clearInterval(player.keepAliveTimerId), clearInterval(player.checkSourceBufferTimerId), player.h = 0, player.l = 0, player.u = 0;
},
H5sPlayerWS.prototype.checkSourceBuffer = function () {
if (void 0 === this._pbconf) {
true === this.v && (console.log("CheckSourceBuffer has been disconnect", this), clearInterval(this.keepAliveTimerId),
clearInterval(this.checkSourceBufferTimerId), clearInterval(this.reconnectTimerId));
try {
if (console.log("CheckSourceBuffer", this), this.sourceBuffer.buffered.length <= 0) {
if (this.h++ , 8 < this.h) {
return console.log("CheckSourceBuffer Close 1"), void this.wsSocket.close();
}
}
else {
this.h = 0;
this.sourceBuffer.buffered.start(0);
var t = this.sourceBuffer.buffered.end(0), s = t - this.video.currentTime;
if (5 < s || s < 0) {
return console.log("CheckSourceBuffer Close 2", s), void this.wsSocket.close();
}
if (t == this.l) {
if (this.u++ , 3 < this.u) {
return console.log("CheckSourceBuffer Close 3"), void this.wsSocket.close();
}
}
else {
this.u = 0;
}
this.l = t;
}
}
catch (err) {
console.log(err)
}
}
},
H5sPlayerWS.prototype.connect = function () {
this.setupWebSocket(this._token);
this.reconnectTimerId = setInterval(this.reconnectFunction.bind(this), 3e3);//没3s重连一次。
},
H5sPlayerWS.prototype.disconnect = function () {
console.log("disconnect", this), this.v = true, clearInterval(this.reconnectTimerId), null != this.wsSocket && (this.wsSocket.close(),
this.wsSocket = null), console.log("disconnect", this);
},
H5sPlayerWS.prototype.start = function () {
try {
var t = {
cmd: "H5_START"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.pause = function () {
try {
var t = {
cmd: "H5_PAUSE"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.resume = function () {
try {
var t = {
cmd: "H5_RESUME"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.seek = function (t) {
try {
var s = {
cmd: "H5_SEEK"
};
s.nSeekTime = t, this.wsSocket.send(JSON.stringify(s))
}
catch (err) {
console.log(err)
}
},
H5sPlayerWS.prototype.speed = function (t) {
try {
var s = {
cmd: "H5_SPEED"
};
s.nSpeed = t, this.wsSocket.send(JSON.stringify(s))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.reconnectFunction = function () {
true === this.S && (console.log("Reconnect..."), this.j(this._token), this.S = false)
},
H5sPlayerRTC.prototype.q = function (t) {
var s;
console.log("H5SWebSocketClient");
try {
"http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
"https:" == this._conf.protocol && (console.log(this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
console.log(this._conf.host)
}
catch (err) {
return void alert("error")
}
return s;
},
H5sPlayerRTC.prototype.keepAlive = function () {
try {
var t = {
type: "keepalive"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.nt = function (t) {
if (t.candidate) {
var s;
console.log("onIceCandidate currentice", t.candidate), s = t.candidate, console.log("onIceCandidate currentice",
s, JSON.stringify(s));
var e = JSON.parse(JSON.stringify(s));
e.type = "remoteice", console.log("onIceCandidate currentice new", e, JSON.stringify(e)), this.wsSocket.send(JSON.stringify(e))
}
else {
console.log("End of candidates.");
}
},
H5sPlayerRTC.prototype.ht = function (t) {
var s;
console.log("Remote track added:" + JSON.stringify(t)), s = t.ct ? t.ct[0] : t.stream;
var e = this._videoElemet;
e.src = URL.createObjectURL(s), e.play();
},
H5sPlayerRTC.prototype.rt = function () {
console.log("createPeerConnection config: " + JSON.stringify(this.T) + " option:" + JSON.stringify(this.I));
var s = new RTCPeerConnection(this.T, this.I), e = this;
return s.onicecandidate = function (t) {
e.nt.call(e, t)
},
void 0 !== s.lt ? s.lt = function (t) {
e.ht.call(e, t)
}
: s.onaddstream = function (t) {
e.ht.call(e, t)
},
s.oniceconnectionstatechange = function (t) {
console.log("oniceconnectionstatechange state: " + s.iceConnectionState)
},
console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.T) + "option:" + JSON.stringify(this.I)),
s
},
H5sPlayerRTC.prototype.at = function (t) {
console.log("ProcessRTCOffer", t);
try {
this.R = this.rt(), this.O.length = 0;
var s = this;
this.R.setRemoteDescription(createRTCSessionDescription(t)), this.R.createAnswer(this.A).then(function (t) {
console.log("Create answer:" + JSON.stringify(t)), s.R.setLocalDescription(t, function () {
console.log("ProcessRTCOffer createAnswer", t), s.s.send(JSON.stringify(t))
},
function () { })
},
function (t) {
alert("Create awnser error:" + JSON.stringify(t))
})
}
catch (err) {
this.disconnect(), alert("connect error: " + err)
}
},
H5sPlayerRTC.prototype.ut = function (t) {
console.log("ProcessRemoteIce", t);
try {
var s = new RTCIceCandidate({
sdpMLineIndex: t.sdpMLineIndex, candidate: t.candidate
});
console.log("ProcessRemoteIce", s), console.log("Adding ICE candidate :" + JSON.stringify(s)),
this.R.addIceCandidate(s, function () {
console.log("addIceCandidate OK")
},
function (t) {
console.log("addIceCandidate error:" + JSON.stringify(t))
})
}
catch (err) {
alert("connect ProcessRemoteIce error: " + err)
}
},
H5sPlayerRTC.prototype.onReceived = function (msg) {
msg.data, ArrayBuffer, msg.data, console.log("RTC received ", msg.data);
var s = JSON.parse(msg.data);
return console.log("Get Message type ", s.type), "offer" === s.type ? (console.log("Process Message type ",
s.type), void this.at(s)) : "remoteice" === s.type ? (console.log("Process Message type ", s.type),
void this.ut(s)) : void (null != this._pbconf && null != this._pbconf.callback && this._pbconf.callback(msg.data, this._pbconf.userdata))
},
H5sPlayerRTC.prototype.j = function (t) {
this.video.autoplay = true;
var s = "api/v1/h5srtcapi", e = "main";
if (void 0 === this._conf.streamprofile || (e = this._conf.streamprofile), void 0 === this._pbconf) {
s = this._conf.rootpath + s + "?token=" + t + "&profile=" + e + "&session=" + this._conf.session;
}
else {
var i = "false", o = "fake";
void 0 === this._pbconf.serverpb || (i = this._pbconf.serverpb), void 0 === this._pbconf.filename || (o = this._pbconf.filename),
s = this._conf.rootpath + s + "?token=" + t + "&playback=true&profile=" + e + "&serverpb=" + i + "&begintime=" + encodeURIComponent(this._pbconf.begintime) + "&endtime=" + encodeURIComponent(this._pbconf.endtime) + "&filename=" + o + "&session=" + this._conf.session
}
console.log(s), this.wsSocket = this.q(s), console.log("setupWebSocket", this.wsSocket), this.wsSocket.binaryType = "arraybuffer",
(this.wsSocket._player = this).wsSocket.onmessage = this.onReceived.bind(this), this.wsSocket.onopen = function () {
console.log("wsSocket.onopen", this._player);
var t = {
type: "open"
};
this._player.s.send(JSON.stringify(t)), this._player.keepAliveTimerId = setInterval(this._player.keepAlive.bind(this._player), 1e3), null != this._player._pbconf && "true" === this._player._pbconf.autoplay && this._player.start();
},
this.wsSocket.onclose = function () {
console.log("wsSocket.onclose", this._player), true === this._player.v ? console.log("wsSocket.onclose disconnect") : this._player.S = true,
this._player.cleanupWebSocket(this._player)
}
},
H5sPlayerRTC.prototype.cleanupWebSocket = function (t) {
console.log("CleanupWebSocket", t), clearInterval(t.keepAliveTimerId), t.h = 0, t.l = 0, t.u = 0;
},
H5sPlayerRTC.prototype.connect = function () {
this.j(this._token), this.reconnectTimerId = setInterval(this.reconnectFunction.bind(this), 3e3);
},
H5sPlayerRTC.prototype.disconnect = function () {
console.log("disconnect", this), this.v = true, clearInterval(this.reconnectTimerId), null != this.wsSocket && (this.wsSocket.close(),
this.wsSocket = null), console.log("disconnect", this);
},
H5sPlayerRTC.prototype.start = function () {
try {
var t = {
cmd: "H5_START"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.pause = function () {
try {
var t = {
cmd: "H5_PAUSE"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.resume = function () {
try {
var t = {
cmd: "H5_RESUME"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.seek = function (t) {
try {
var s = {
cmd: "H5_SEEK"
};
s.nSeekTime = t, this.wsSocket.send(JSON.stringify(s))
}
catch (err) {
console.log(err)
}
},
H5sPlayerRTC.prototype.speed = function (t) {
try {
var s = {
cmd: "H5_SPEED"
};
s.nSpeed = t, this.wsSocket.send(JSON.stringify(s))
}
catch (err) {
console.log(err)
}
},
H5sPlayerHls.prototype.q = function (t) {
var s;
console.log("H5SWebSocketClient");
try {
"http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
"https:" == this._conf.protocol && (console.log(this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
console.log(this._conf.host)
}
catch (err) {
return void alert("error")
}
return s;
},
H5sPlayerHls.prototype.keepAlive = function () {
try {
var t = {
type: "keepalive"
};
this.wsSocket.send(JSON.stringify(t))
}
catch (err) {
console.log(err)
}
},
H5sPlayerHls.prototype.onReceived = function (msg) {
console.log("HLS received ", msg.data)
},
H5sPlayerHls.prototype.j = function (t) {
var s = "api/v1/h5swscmnapi";
s = this._conf.rootpath + s + "?token=" + t + "&session=" + this._conf.session, console.log(s), this.wsSocket = this.q(s),
console.log("setupWebSocket", this.wsSocket), this.wsSocket.binaryType = "arraybuffer", (this.wsSocket._player = this).wsSocket.onmessage = this.onReceived.bind(this),
this.wsSocket.onopen = function () {
console.log("wsSocket.onopen", this._player), this._player.keepAliveTimerId = setInterval(this._player.keepAlive.bind(this._player), 1e3);
},
this.wsSocket.onclose = function () {
console.log("wsSocket.onclose", this._player), this._player.cleanupWebSocket(this._player)
}
},
H5sPlayerHls.prototype.cleanupWebSocket = function (t) {
console.log("H5sPlayerHls CleanupWebSocket", t), clearInterval(t.keepAliveTimerId)
},
H5sPlayerHls.prototype.dt = function () {
console.log("HLS video.ended", this.g.ended), console.log("HLS video.currentTime", this.g.currentTime);
var t = this.g.currentTime, s = t - this.B;
console.log("HLS diff", s), 0 === s && this.U++ , this.B = t, 3 < this.U && (null != this.wsSocket && (this.wsSocket.close(),
this.wsSocket = null), this.j(this._token), console.log("HLS reconnect"), this.g.src = "", this.B = 0, this.U = 0,
this.g.src = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "hls/" + this.N + "/" + this._token + "/hls.m3u8",
this.g.play());
},
H5sPlayerHls.prototype.connect = function () {
this.j(this._token), this.B = 0, this.U = 0, this.g.onended = function (t) {
console.log("The End")
},
this.g.onpause = function (t) {
console.log("Pause")
},
this.g.onplaying = function (t) {
console.log("Playing")
},
this.g.onseeking = function (t) {
console.log("seeking")
},
this.g.onvolumechange = function (t) {
console.log("volumechange")
},
this.g.src = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "hls/" + this.N + "/" + this._token + "/hls.m3u8",
this.g.play(), this.J = setInterval(this.dt.bind(this), 3e3);
},
H5sPlayerHls.prototype.disconnect = function () {
clearInterval(this.J), this.B = 0, this.U = 0, null != this.wsSocket && (this.wsSocket.close(), this.wsSocket = null),
console.log("disconnect", this);
},
H5sPlayerAudio.prototype.q = function (t) {
var s;
console.log("H5SWebSocketClient");
try {
"http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
"https:" == this._conf.protocol && (console.log(this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
console.log(this._conf.host)
}
catch (err) {
return void alert("error")
}
return s;
},
H5sPlayerAudio.prototype.keepAlive = function () {
try {
this.wsSocket.send("keepalive")
}
catch (err) {
console.log(err)
}
},
H5sPlayerAudio.prototype.onReceived = function (msg) {
for (var s = new Int16Array(msg.data), e = s.length, i = this._.createBuffer(1, e, 8e3), o = 0; o < 1; o++) {
for (var n = i.getChannelData(o), h = 0; h < e; h++) {
n[h] = s[h] / 16383.5;
}
}
var c = this._.createBufferSource();
c.buffer = i, c.connect(this._.destination), c.start();
},
H5sPlayerAudio.prototype.cleanupWebSocket = function (t) {
console.log("CleanupWebSocket", t), clearInterval(t.keepAliveTimerId)
},
H5sPlayerAudio.prototype.j = function (t) {
var s = "api/v1/h5saudapi";
s = this._conf.rootpath + s + "?token=" + t + "&session=" + this._conf.session, console.log(s), this.wsSocket = this.q(s),
console.log("setupWebSocket for audio", this.wsSocket), this.wsSocket.binaryType = "arraybuffer", (this.wsSocket._player = this).wsSocket.onmessage = this.onReceived.bind(this),
this.wsSocket.onopen = function () {
console.log("wsSocket.onopen", this._player), this._player.keepAliveTimerId = setInterval(this._player.keepAlive.bind(this._player), 1e3);
},
this.wsSocket.onclose = function () {
console.log("wsSocket.onclose", this._player), this._player.cleanupWebSocket(this._player)
}
},
H5sPlayerAudio.prototype.connect = function () {
this.j(this._token)
},
H5sPlayerAudio.prototype.disconnect = function () {
console.log("disconnect", this), null != this.wsSocket && (this.wsSocket.close(), this.wsSocket = null), console.log("disconnect",
this);
},
H5sPlayerAudBack.prototype.q = function (t) {
var s;
console.log("H5SWebSocketClient");
try {
"http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
"https:" == this._conf.protocol && (console.log(this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
console.log(this._conf.host)
}
catch (err) {
return void alert("error")
}
return s;
},
H5sPlayerAudBack.prototype.keepAlive = function () {
try {
this.wsSocket.send("keepalive")
}
catch (err) {
console.log(err)
}
},
H5sPlayerAudBack.prototype.onReceived = function (msg) { },
H5sPlayerAudBack.prototype.cleanupWebSocket = function (t) {
console.log("CleanupWebSocket", t), clearInterval(t.keepAliveTimerId)
},
H5sPlayerAudBack.prototype.K = function () {
console.log("sampleRate", this._.sampleRate), navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.ft;
try {
navigator.getUserMedia({
video: false, audio: true
},
this.St.bind(this))
}
catch (err) {
return void alert("Audio back false getUserMedia", err);
}
},
H5sPlayerAudBack.prototype.yt = function () {
this.G = true
},
H5sPlayerAudBack.prototype.j = function (t) {
var s = "api/v1/h5saudbackapi";
s = this._conf.rootpath + s + "?token=" + t + "&samplerate=" + this.D + "&session=" + this._conf.session,
console.log(s), this.wsSocket = this.q(s), console.log("setupWebSocket for audio back", this.wsSocket), this.wsSocket.binaryType = "arraybuffer",
(this.wsSocket._player = this).wsSocket.onmessage = this.onReceived.bind(this), this.wsSocket.onopen = this.yt.bind(this), this.wsSocket.onclose = function () {
console.log("wsSocket.onclose", this._player), this._player.cleanupWebSocket(this._player)
}
},
H5sPlayerAudBack.prototype.vt = function (t) {
var s = float32ToInt16(t.inputBuffer.getChannelData(0));
true === this.G && this.wsSocket && this.wsSocket.send(s)
},
H5sPlayerAudBack.prototype.St = function (t) {
try {
var s = this._.createMediaStreamSource(t), e = this._.createScriptProcessor(1024, 1, 1);
s.connect(e), e.connect(this._.destination), e.onaudioprocess = this.vt.bind(this)
}
catch (err) {
return void alert("Audio intecomm error", err);
}
},
H5sPlayerAudBack.prototype.connect = function () {
this.j(this._token)
},
H5sPlayerAudBack.prototype.disconnect = function () {
console.log("disconnect", this), null != this.wsSocket && (this.wsSocket.close(), this.wsSocket = null), console.log("disconnect",
this);
};
2.创建简单播放视频原型代码
结合前面H5Stream里面的h5splayer.js,实验并成功播放了一个H5Stream的ws视频。
还有一些细节问题。
<html>
<head>
<title>WebsocketVideo</title>
<script src="ws.js"></script>
<script src="jquery.js"></script>
</head>
<body>
<input style="width:100px;">
<button id="btnPlay">Play</button>
<div>
<video id="video1" autoplay webkit-playsinline playsinline></video>
</div>
</body>
<script>
$(document).ready(function(){
var conf={};
conf.url="ws://localhost:8080/api/v1/h5swsapi?token=token2&profile=main&session=c1782caf-b670-42d8-ba90-2244d0b0ee83";
conf.videoId='video1';
var player=new WebSocketPlayer(conf);
player.openWebSocket();
});
function WebSocketPlayer(conf){
this.conf=conf;
this.strCodec='';
this.inited=false;
this.buffer=[];
this.openWebSocket=function(){
console.log('openWebSocket');
var player=this;
var url=player.conf.url;
var wsImp=window.WebSocket || window.MozWebSocket;
var ws=new wsImp(url);
ws.binaryType='arraybuffer';
ws.onopen=function(){
console.log('onopen');
};
ws.onclose=function(){
console.log('onclose');
}
ws.onmessage=player.onReceived;
ws.player=player;
};
this.onReceived=function(msg){
console.log('onmessage',msg.data);
var ws=this;
var player=ws.player;
if(player.inited===false){
player.inited=true;
player.strCodec=String.fromCharCode.apply(null,new Uint8Array(msg.data));
player.initMediaSource(player);
console.log(player.strCodec);
}else{
//player.buffer.push(msg.data);
//player.readFromBuffer();
player.sourceBuffer.appendBuffer(msg.data);
}
};
this.initMediaSource=function(player){
try {
console.log('initMediaSource',player);
var msImp=window.MediaSource || window.WebKitMediaSource;
var ms=new msImp();
ms.player=player;
player.ms=ms;
var video=document.getElementById(player.conf.videoId);
video.src=URL.createObjectURL(ms);
video.play();
ms.addEventListener('sourceopen',player.msSourceOpen)
player.video=video;
}catch(ex){
console.error(ex);
}
};
this.msSourceOpen=function(){
console.log('msSourceOpen');
var ms=this;
var player=ms.player;
var buffer=ms.addSourceBuffer(player.strCodec);
ms.duration=Infinity;
buffer.addEventListener('updateend',player.readFromBuffer)
player.sourceBuffer=buffer;
};
this.readFromBuffer=function(){
console.log('readFromBuffer1',this);
//var player=this;
//var buffer=player.buffer;
//console.log('readFromBuffer2',buffer);
//var first=buffer.shift();
//var sourceBuffer=player.sourceBuffer;
//sourceBuffer.appendBuffer(first);
};
}
</script>
</html>