影片的播放,可以使用 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>
