视频流播放视频可以通过多种方式实现,包括嵌入iframe、使用RTSP取流URL、以及利用特定的软件或平台进行流媒体传输。
-
嵌入iframe:可以通过在网页中嵌入iframe的方式来显示视频流。这种方式适用于在网页中直接展示视频流,但可能会遇到层级和显示问题,需要通过条件判断来展示或隐藏视频流1。
-
使用RTSP取流URL:对于需要实时监控或远程访问的视频流,可以使用RTSP(Real Time Streaming Protocol)取流URL来获取视频流。这通常涉及到从摄像头或视频服务器获取RTSP地址,然后通过特定的软件或平台进行播放。例如,海康摄像头可以通过自带说明获取RTSP取流URL,或者通过综合安防管理平台获取。在播放时,如果视频编码类型为H.264,可以直接播放;如果为H.265,则可能需要转换编码类型,因为某些播放器可能不支持H.265编码2。
-
利用特定软件或平台:例如,webrtc-streamer可以用来播放RTSP视频流。这涉及到安装和配置webrtc-streamer软件,并通过该软件播放RTSP视频流。此外,对于Apple设备,还可以使用“隔空播放”功能将内容流播放到兼容的设备上,如Apple TV、Mac或兼容“隔空播放”的智能电视13。
如遇到H.265编码类型视频 ↓↓↓↓↓↓↓↓↓
<!DOCType html>
<html>
<head>
<link href="/favicon.ico" rel="icon" type="image/x-icon" />
<meta charset="utf-8">
<title>h265webjs - https://github.com/numberwolf/h265web.js</title>
<meta charset="utf-8" name="author" content="ChangYanlong">
<meta charset="utf-8" name="email" content="porschegt23@foxmail.com">
<meta charset="utf-8" name="discord" content="numberwolf#8694">
<meta charset="utf-8" name="github" content="https://github.com/numberwolf/h265web.js">
<script src="dist/missile.js"></script>
<script src="dist/h265webjs-v20221106.js"></script>
<!--<script src="dist-multi-thread/missile-multi-thread.js"></script>
<script src="dist-multi-thread/h265webjs-v20221106.js"></script>-->
<style>
</style>
</head>
<body>
<div style="width:1190px;background-color: #e9e9e9;">
<div style="width:100%; height:20px; background-color:blue; color:white;">
Player Area
</div>
<div style="width:100%;height:360px;overflow:hidden;">
<div id="glplayer" style="width: 640px; height: 360px; background-color: #c9c9c9;float:left">
</div>
<div style="width: 550px; height: 360px; float:left; background-color:black; overflow:hidden;">
<div style="width:100%; height:25px; background-color:blue; color:white;">
1. Input Play URL (Editable)
</div>
<!-- <input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="http://127.0.0.1/live/test.flv"> -->
<input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="example_normal/hevc_test_moov_set_head_16s.mp4">
<!--<input id="url-input" style="width:100%; height: 20px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);" value="http://flv.vaiwan.com/live/test.live.flv">-->
</input>
<div style="width:100%; height:25px; background-color:blue; color:white;">
2. Input Player Config (Editable)
</div>
<textarea id="config-input" style="width:100%; height: 280px; background-color: rgba(30,31,20,1); color:rgba(240,181,53,1);">
{
"player": "glplayer",
"width": 640,
"height": 360,
"token" : "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1",
"extInfo" : {
"probeSize" : 8192,
"ignoreAudio" : 0,
"coreProbePart" : 0.1,
"autoPlay" : false,
"cacheLength" : 50,
"rawFps": 24
}
}
</textarea>
</div>
</div>
<hr>
<div style="width:100%;height: 200px; overflow: hidden">
<div style="width:360px;height:200px;float:left;">
<div style="width:100%; height:20px; background-color:blue; color:white;">
SnapShot
</div>
<canvas id="snapshot-canvas" style="width: 360px; height: 180px; background-color: #000000;">
</canvas>
</div>
<div style="width:830px;height:200px;background-color:black;float:left;">
<div style="width:100%; height:20px; background-color:blue; color:white;">
Event Log
</div>
<div style="width:100%;height:170px;overflow: hidden;">
<textarea disabled="disabled" id="logger" style="width: 300px; height: 170px; background-color: #000000; color:white; float:left">
events
--------------------</textarea>
<textarea disabled="disabled" id="logger-cache" style="width: 250px; height: 170px; background-color: #000000; color:white;float:left">
cache log</textarea>
<textarea disabled="disabled" id="logger-pts" style="width: 250px; height: 170px; background-color: #000000; color:white; float:left">
pts log</textarea>
</div>
</div>
</div>
<hr>
<button style="background-color:blue;color:white;" onclick="installPlayer()">1.Install</button>
<button style="background-color:red;" onclick="releasePlayer()">2.Release</button>
|
<button onclick="playPausePlayer()" id="play-button" disabled>1.Play/Pause</button>
<button onclick="seekPlayer()">2.Seek To 5s</button>
<button onclick="mutePlayer()">3.Mute(Volume 0.0)</button>
<button onclick="unmutePlayer()">4.Volume To 1.0</button>
|
<button onclick="fullscreenPlayer()">1.Fullscreen</button>
|
<button onclick="nextFrame()">1.Next Frame</button>
<button onclick="snapshot()">2.Snapshot</button>
<button onclick="playrate(0.5)">3.PlayRate 0.5</button>
<button onclick="resize(640, 200)">resize640x200</button>
<hr>
</div>
<pre>
--> 1.Install Player
--> when [onReadyShowDone] happened
--> 2.Play/Pause/Seek/Other operations
--> 3.Release Player
</pre>
<a href="https://github.com/numberwolf/h265web.js">https://github.com/numberwolf/h265web.js</a>
<script>
if((/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))) {
alert("safari");
}
const h265webURL = "https://github.com/numberwolf/h265web.js";
var playerObj = null;
var loggerObj = document.getElementById("logger");
var loggerCacheObj = document.getElementById("logger-cache");
var loggerPtsObj = document.getElementById("logger-pts");
function clear() {
window.STATICE_MEM_playerCount = -1;
window.STATICE_MEM_playerIndexPtr = 0;
} // end func clear
function releasePlayer() {
if (playerObj !== null) {
playerObj.release();
playerObj = null;
// log
loggerObj.value = h265webURL + "\r\nRelease done!";
document.getElementById("play-button").setAttribute("disabled", "disabled");
}
}
function installPlayer() {
clear();
const textarea_conf = document.getElementById("config-input");
const textarea_conf_value = textarea_conf.value;
const config = JSON.parse(textarea_conf_value);
const play_url = document.getElementById("url-input").value;
console.log(textarea_conf_value);
console.log(config);
console.log(play_url);
/*
*
*
* 1. create player object
*
*
*/
playerObj = window.new265webjs(play_url, config);
/*
*
*
* 2. bind events
*
*
*/
playerObj.onSeekStart = (pts) => {
loggerObj.scrollNewest("\r\nonSeekStart:" + pts);
};
playerObj.onSeekFinish = () => {
loggerObj.scrollNewest("\r\nonSeekFinish");
};
playerObj.onPlayFinish = () => {
loggerObj.scrollNewest("\r\nonPlayFinish");
};
playerObj.onRender = (width, height, imageBufferY, imageBufferB, imageBufferR) => {
loggerObj.scrollNewest("\r\nonRender");
};
playerObj.onOpenFullScreen = () => {
loggerObj.scrollNewest("\r\nonOpenFullScreen");
};
playerObj.onCloseFullScreen = () => {
loggerObj.scrollNewest("\r\nonCloseFullScreen");
};
playerObj.onSeekFinish = () => {
loggerObj.scrollNewest("\r\nonSeekFinish");
};
playerObj.onLoadCache = () => {
loggerObj.scrollNewest("\r\nonLoadCache");
};
playerObj.onLoadCacheFinshed = () => {
loggerObj.scrollNewest("\r\nonLoadCacheFinshed");
};
playerObj.onReadyShowDone = () => {
loggerObj.scrollNewest("\r\nonReadyShowDone:【You can play now】");
document.getElementById("play-button").removeAttribute("disabled");
};
playerObj.onLoadFinish = () => {
loggerObj.scrollNewest("\r\nonLoadFinish");
playerObj.setVoice(1.0);
mediaInfo = playerObj.mediaInfo();
console.log("onLoadFinish mediaInfo===========>", mediaInfo);
/*
meta:
isHEVC: true
durationMs: 144400
fps: 25
sampleRate: 44100
size: {
width: 864,
height: 480
},
audioNone : false
videoType: "vod"
*/
let codecName = "h265";
if (mediaInfo.meta.isHEVC === false) {
loggerObj.scrollNewest("\r\nonLoadFinish is Not HEVC/H.265");
codecName = "h264";
} else {
loggerObj.scrollNewest("\r\nonLoadFinish is HEVC/H.265");
}
loggerObj.scrollNewest("\r\nonLoadFinish media Codec:" + codecName);
loggerObj.scrollNewest("\r\nonLoadFinish media FPS:" + mediaInfo.meta.fps);
loggerObj.scrollNewest("\r\nonLoadFinish media size:" + mediaInfo.meta.size.width + "x" + mediaInfo.meta.size.height);
if (mediaInfo.meta.audioNone) {
loggerObj.scrollNewest("\r\nonLoadFinish media no Audio");
} else {
loggerObj.scrollNewest("\r\nonLoadFinish media sampleRate:" + mediaInfo.meta.sampleRate);
}
if (mediaInfo.videoType == "vod") {
loggerObj.scrollNewest("\r\nonLoadFinish media is VOD");
loggerObj.scrollNewest("\r\nonLoadFinish media dur:" + Math.ceil(mediaInfo.meta.durationMs) / 1000.0);
} else {
loggerObj.scrollNewest("\r\nonLoadFinish media is LIVE");
}
};
playerObj.onCacheProcess = (cPts) => {
loggerCacheObj.scrollNewest("onCacheProcess:" + cPts);
};
playerObj.onPlayTime = (videoPTS) => {
if (mediaInfo.videoType == "vod") {
loggerPtsObj.scrollNewest("onPlayTime:" + videoPTS);
} else {
// LIVE
}
};
/*
*
*
* 3. install player
*
*
*/
playerObj.do();
} // end func installPlayer
function playPausePlayer() {
if (playerObj !== null) {
if (playerObj.isPlaying()) {
loggerObj.scrollNewest("\r\nplayerObj.pause()");
playerObj.pause();
} else {
loggerObj.scrollNewest("\r\nplayerObj.play()");
playerObj.play();
}
}
} // end func playPausePlayer
function seekPlayer() {
loggerObj.scrollNewest("\r\nplayerObj.seek(5)");
if (playerObj !== null) {
playerObj.seek(5);
}
} // end func seekPlayer
function mutePlayer() {
loggerObj.scrollNewest("\r\nplayerObj.setVoice(0)");
if (playerObj !== null) {
playerObj.setVoice(0);
}
} // end func mutePlayer
function unmutePlayer() {
loggerObj.scrollNewest("\r\nplayerObj.setVoice(1.0)");
if (playerObj !== null) {
playerObj.setVoice(1.0);
}
} // end func unmutePlayer
function fullscreenPlayer() {
loggerObj.scrollNewest("\r\nplayerObj.fullScreen()");
if (playerObj !== null) {
playerObj.fullScreen();
}
}
function nextFrame() {
loggerObj.scrollNewest("\r\nplayerObj.playNextFrame()");
if (playerObj !== null) {
playerObj.playNextFrame();
}
}
function snapshot() {
const snapCanvas = document.querySelector("#snapshot-canvas");
if (playerObj !== null) {
playerObj.snapshot(snapCanvas);
loggerObj.scrollNewest("\r\nplayerObj.snapshot");
}
}
function playrate(rate=1.0) {
console.log(playerObj.player.videoTag);
if (playerObj !== null) {
let ret = playerObj.setPlaybackRate(rate);
loggerObj.scrollNewest(
"\r\nplayerObj playrate:"
+ ' ret:' + ret
+ ' tag:' + rate
+ ' res:' + playerObj.getPlaybackRate());
}
}
function resize(w, h) {
if (playerObj !== null) {
let ret = playerObj.resize(w, h);
loggerObj.scrollNewest(
"\r\nplayerObj resize:"
+ ' ret:' + ret
+ ' w:' + w
+ ' h:' + h);
}
}
window.onload = function() {
if (loggerObj === null) {
loggerObj = document.getElementById("logger");
loggerCacheObj = document.getElementById("logger-cache");
loggerPtsObj = document.getElementById("logger-pts");
}
loggerObj.scrollNewest = function(val) {
loggerObj.value += val;
loggerObj.scrollTop = loggerObj.scrollHeight;
};
loggerCacheObj.scrollNewest = function(val) {
loggerCacheObj.value = val;
//loggerCacheObj.scrollTop = loggerCacheObj.scrollHeight;
};
loggerPtsObj.scrollNewest = function(val) {
loggerPtsObj.value = val;
//loggerPtsObj.scrollTop = loggerPtsObj.scrollHeight;
};
}; // end onload
</script>
</body>
</html>
详情开源demo地址:https://github.com/numberwolf/h265web.js