build/live-push.html

283 lines
9.5 KiB
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
<meta content="telephone=no" name="format-detection">
<title>头歌考试系统</title>
<style>
* {
margin: 0;
padding: 0;
}
#id_local_video {
position: absolute;
width: 100%;
height: 100%;
z-index: 3;
display: none;
}
#id_local_video video {
height: 100%;
width: 100%;
object-fit: cover !important;
}
button {
position: relative;
width: 69%;
height: 44px;
line-height: 44px;
font-size: 16px;
text-align: center;
margin-top: 60px;
background: linear-gradient(90deg, #74C2FF 0%, #2EA4FF 100%);
-webkit-appearance: none;
border-radius: 44px;
border: none;
color: #FFF;
outline: none;
}
.wrp {
text-align: center;
}
.wrp img {
width: 69%;
margin-bottom: 25px;
margin-top: 60px;
}
#model {
display: none;
position: fixed;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .6);
z-index: 200;
}
#model>div {
width: 80%;
height: 162px;
background: #FFF;
margin-left: 10%;
position: absolute;
top: 50%;
margin-top: -81px;
border-radius: 6px;
}
#model .con {
height: 120px;
padding: 0 15px;
text-align: center;
color: #333;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
#model .btn {
font-size: 14px;
height: 40px;
line-height: 40px;
text-align: center;
border-top: 1px solid #eee;
}
</style>
</head>
<body>
<script src="https://imgcache.qq.com/open/qcloud/live/webrtc/js/TXLivePusher-1.0.2.min.js" charset="utf-8"></script>
<div id="model">
<div>
<div class="con" id="text"></div>
<div class="btn" onclick="location.reload()">确定</div>
</div>
</div>
<div id="id_local_video" style="width:100%;display:none;align-items:center;justify-content:center;">
</div>
<div class="wrp">
<img src="/images/user_camera.png" />
<div class="tip">请按图示调整手机录制角度!</div>
<button onclick="liveVideo()">开始录制</button>
</div>
<script>
let liveUrl;
let timer;
let API_SERVER = "";
if (document.domain === "www.educoder.net" || document.domain === "kepukehuan.educoder.net" || document.domain === "localhost") {
API_SERVER = "data"
} else {
API_SERVER = document.domain.split(".")[0] + "-data"
}
var Cookie = {
get: function (k) {
return ((new RegExp(["(?:; )?", k, "=([^;]*);?"].join(""))).test(document.cookie) && RegExp["$1"]) || "";
},
set: function (k, v, e, d) {
var date = new Date();
var expiresDays = e;
date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);
document.cookie = k + "=" + v + "; expires=" + (e != '' ? date.toGMTString() : "GMT_String") + ";path=/;domain=" + (d || document.domain);
},
del: function (k, d) {
document.cookie = k + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;domain=" + (d || _options.domain);
document.cookie = k + "=v; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";
}
};
var pattern = /(\w+)=([^\#&]*)/ig;
var parames = {};
location.href.replace(pattern, function (attr, key, value) {
parames[key] = decodeURI(value);
});
Cookie.set("_educoder_session", parames.cookie)
Cookie.set("_educoder_session", parames.cookie, 1, "educoder.net")
console.log("parames:", parames)
async function getData() {
const res = await fetch("https://" + API_SERVER + ".educoder.net" + "/api/exercises/" + parames.id + "/video_push_url.json?login=" + parames.login, {
method: 'GET',
credentials: "include",
mode: "cors"
}).then(r => r.json())
liveUrl = res.url;
// window.liveVideo(res.url);
console.log("res:", res)
}
getData()
async function saveData() {
const res = await fetch("https://" + API_SERVER + ".educoder.net" + "/api/exercises/" + parames.id + "/save_video_url.json?login=" + parames.login, {
method: 'POST',
credentials: "include",
body: JSON.stringify({
video_url: "https://live-stream.educoder.net/live/" + parames.id + "-" + parames.login + ".m3u8",
exercise_user_id: parames.login
}),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
},
mode: "cors"
}).then(r => r.json())
}
</script>
<script type="text/javascript">
var dom = document.getElementById("model");
var text = document.getElementById("text");
const pushError = function (e) {
switch (e) {
case -1:
text.innerHTML = ("WebRTC 接口调用失败");
break;
case -2:
text.innerHTML = ("请求服务器推流接口返回报错");
break;
case -1001:
text.innerHTML = ("打开摄像头失败")
break;
case -1002:
text.innerHTML = ("打开麦克风失败")
break;
case -1005:
text.innerHTML = ("摄像头被中断(设备被拔出或者权限被用户取消)")
break;
case -1006:
text.innerHTML = ("麦克风被中断(设备被拔出或者权限被用户取消)")
break;
default:
text.innerHTML = ("推流错误,请刷新后再试")
break;
}
dom.style.display = "block"
}
window.addEventListener("offline", function () {
text.innerHTML = ("您的网络已断开,请连接网络后再试")
dom.style.display = "block"
})
window.addEventListener("netchange",function(){
text.innerHTML = ("您的网络已切换,点击确定后重新开始录制")
dom.style.display = "block"
})
function liveVideo(url) {
// liveUrl = 'live-stream-push.educoder.net/live/11?txSecret=0b401937c270954c127c8ad249d9030c&txTime=6243F6AD'
url = url || liveUrl
if (!liveUrl) {
alert("未获取到推流地址")
return;
}
try {
window.livePusher = new TXLivePusher();
livePusher.setRenderView('id_local_video');
livePusher.setVideoQuality('180p');
livePusher.setAudioQuality('standard');
livePusher.setProperty('setVideoFPS', 25);
livePusher.startCamera();
livePusher.startMicrophone();
var hasVideo = false;
var hasAudio = false;
var isPush = false;
livePusher.setObserver({
onError: function (e) {
// pushError(e)
livePusher.startPush('webrtc://' + url);
setTimeout(() => {
// console.log("重新推流1")
// livePusher.startPush('webrtc://' + url);
}, 1500)
},
onCaptureFirstAudioFrame: function () {
hasAudio = true;
if (hasVideo && !isPush) {
isPush = true;
saveData()
livePusher.startPush('webrtc://' + url);
}
},
onCaptureFirstVideoFrame: function () {
hasVideo = true;
if (hasAudio && !isPush) {
isPush = true;
saveData()
livePusher.startPush('webrtc://' + url);
}
}
});
document.getElementById("id_local_video").style.display = "block";
timer = setInterval(() => {
if (!livePusher.isVideoPushing) {
console.log("重新推流")
livePusher.stopPush();
livePusher.startPush('webrtc://' + url);
}
}, 10 * 1000)
} catch (e) {
debugger
alert(e)
}
}
</script>
</body>
</html>