影片的播放,可以使用 Video.js,完整 html 如下。
簡易影片播放
todo
data-setup 屬性
Video.js 官網教學中,常把 data-setup 屬性列於 html 中,這會導致在 Javascript 程式碼中失效。
官網教學如下
<video id="video1" class="video-js vjs-default-skin vjs-big-play-centered" controls
crossorigin="use-credentials"
data-setup='{ "autoplay": true, "controls": true , "poster": "", "preload": "auto" }'>
實際上需寫在 Javascript 中,如下所示
<body>
<video id="video1" class="videobox video-js vjs-default-skin vjs-big-play-centered"></video>
<script>
videojs(
"video1",
{
controls:true,
muted: true,
autoplay: true,
fluid: true,
aspectRatio: "16:9",
requestFullScreen: true,
notSupportedMessage: "no connection",
sources: [{src:url,type:"application/x-mpegURL"}]
}
);
</script>
</body>
m3u8播放
m3u8 是直播系統的播放列表,開始直播時才會產生 index.m3u8檔。所以觀看者若在還沒開始直播前就進入網頁,會讓網頁一直轉圈圈。就算轉到開始直播時,還是無法進入直播狀態。
底下使用 ajax 每 1 秒就檢查伺服器是否有 /data/video/live/channel_xx/index.m3u8,如果有的話就開始播放,沒有就停止。完整 html 如下
{% extends 'base.html' %}
{% block content1 %}
<style>
table{
border: 1px solid #0000ff;
border-collapse:collapse;
margin:0px;
}
tr{
border:1px solid #000000;
margin:0px;
}
td{
border:1px solid #00a0ff;
padding:0px;
width:750px;
height: 420;
position:relative;
}
.videobox{
position:absolute;
width: 100%;
height: 100%;
top:0px;
left:0px;
z-index:0;
}
#showbox1{
background-color: #000000;
opaity: 0.5;
font-size: 16px;
color:#FFFFFF;
font-weight:bold;
position:absolute;
top:5px;
left:5px;
z-index:0;
}
#showbox2{
background-color: #000000;
opacity: 0.5;
font-size: 16px;
color:#FFFFFF;
font-weight:bold;
position:absolute;
top:5px;
left:5px;
z-index:0;
}
#refresh{
position:absolute;
right:5px;
top:5px;
height:25px;
z-index:0;
overflow:hidden;
background: rgba(255, 255, 255, 0.3)
}
.divshell{
position: relative;
background-color: #ffffff;
width: 100%;
height: 100%;
margin:0px;
}
.vjs-default-skin { color: #fdfdfd; }
.vjs-default-skin .vjs-play-progress,
.vjs-default-skin .vjs-volume-level { background-color: #1880b8 }
.vjs-default-skin .vjs-control-bar { font-size: 100% }
</style>
<p></p>
<table>
<tr>
<td>
<div id="div1" class="divshell">
<div id="div_video1" class="divshell" style="position: absolute;z-index: 0">
<video id="video1" class="videobox video-js vjs-default-skin vjs-big-play-centered"></video>
<div id="showbox1"></div>
</div>
<div id="conn_video1" class="divshell" style="position:absolute;z-index: 1;">
<table width="100%" height="100%" align="center" valign="center">
<tr>
<td align="center">
<font color="#000088">
Video 1 直播系統<br>
Supported for all browsers<br><br>
</font>
<font color="#008800">
Camera Connecting...
</font>
</td>
</tr>
</table>
</div>
</div>
</td>
<td>
<div id="div2" class="divshell">
<div id="div_video2" class="divshell" style="position: absolute;z-index: 0">
<video id="video2" class="videobox video-js vjs-default-skin vjs-big-play-centered"></video>
<div id="showbox2"></div>
</div>
<div id="conn_video2" class="divshell" style="position:absolute;z-index: 1;">
<table width="100%" height="100%" align="center" valign="center">
<tr>
<td align="center">
<font color="#000088">
Video 2 直播系統<br>
Supported for all browsers<br><br>
</font>
<font color="#008800">
Camera Connecting...
</font>
</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table> <script> function check_url(index){ video=videos[index]; url=urls[index]; if (window.XMLHttpRequest) conn=new XMLHttpRequest(); else conn=new ActiveXObject("Microsoft.XMLHTTP"); conn.open("GET", url, false); conn.send(); if (conn.readyState==4 && conn.status==200){ document.getElementById(`div_video${index+1}`).style.zIndex=1; document.getElementById(`conn_video${index+1}`).style.zIndex=0; if (video.techGet_("paused")){ video.load(); video.play(); } } else{ document.getElementById(`div_video${index+1}`).style.zIndex=0; document.getElementById(`conn_video${index+1}`).style.zIndex=1; } } function videoStuck(video, index){ var currentTime = video.currentTime(); if(currentTime == lastTimes[index]){ video.load(); video.play(); }else{ lastTimes[index] = currentTime; } } lastTimes=[0,0,0,0,0,0] urls=[]; videos=[]; for (i=0;i<6;i++){ urls[i]=`/live/channel_${i+1}/index.m3u8` videos[i]=videojs( `video${i+1}`, { controls:true,muted: true,autoplay: true,fluid: true,aspectRatio: "16:9", requestFullScreen: true,notSupportedMessage: "no connection" }); videos[i].src([{src:urls[i],type:"application/x-mpegURL"}]); check_url(i); setInterval(check_url,1000, i); setInterval(videoStuck,3000,videos[i],i); } //t3=setInterval(showTime,1000); /* function showTime(){ var NowDate = new Date(); var year = NowDate.getFullYear(); var month = NowDate.getMonth()+1; var day = NowDate.getDate(); var h = NowDate.getHours(); var m = NowDate.getMinutes(); var s = NowDate.getSeconds(); if (month<10)month = "0"+month; if (day<10)day = "0"+day; if (h<10)h = "0"+h; if (m<10)m = "0"+m; if (s<10)s = "0"+s; var t=`${year}/${month}/${day} ${h}:${m}:${s}`; document.getElementById('showbox1').innerHTML = t; document.getElementById('showbox2').innerHTML = t; } */ </script> {% endblock %}
純 video.js
底下代碼為進化版本,完全使用 video.js,不依靠伺服器的檢查程式。當播放的 currentTime == 0 表示沒有播放,currentTime >0 表示開始播放。
<script>
function startVideo(video, index) { var currentTime = video.currentTime(); //document.getElementById("showbox1").innerHTML=currentTime+":"+lastTimes[1]; if (currentTime==0){ document.getElementById(`div_video${index+1}`).style.zIndex=0; document.getElementById(`conn_video${index+1}`).style.zIndex=1; } else{ document.getElementById(`div_video${index+1}`).style.zIndex=1; document.getElementById(`conn_video${index+1}`).style.zIndex=0; } if(currentTime == lastTimes[index]){ video.load(); video.play(); } else{ lastTimes[index] = currentTime; } } urls=[]; var videos=[]; var lastTimes=[0,0,0,0,0,0]; for (i=0;i<6;i++){ urls[i]=`/live/channel_${i+1}/index.m3u8` videos[i]=videojs( `video${i+1}`, { controls:true,muted: true,autoplay: true,fluid: true,aspectRatio: "16:9", requestFullScreen: true,notSupportedMessage: "no connection" }); videos[i].src([{src:urls[i],type:"application/x-mpegURL"}]); startVideo(videos[i], i); setInterval(startVideo,1000,videos[i],i); }
</script>