mirror of
https://github.com/Monibuca/plugin-preview.git
synced 2026-04-23 00:27:11 +08:00
feat: upgrade to jesscibuca pro demo
This commit is contained in:
@@ -53,7 +53,7 @@ func (p *PreviewConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
//w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
|
||||
//w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
|
||||
b, err = f.ReadFile("ui/index.html")
|
||||
b, err = f.ReadFile("ui/demo.html")
|
||||
w.Write(b)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Executable
BIN
Binary file not shown.
+14
-1
File diff suppressed because one or more lines are too long
Binary file not shown.
+14
-1
File diff suppressed because one or more lines are too long
Binary file not shown.
+554
@@ -0,0 +1,554 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Preview by JessibucaPro</title>
|
||||
<script src="./vconsole.js"></script>
|
||||
<script src="./jessibuca-pro-demo.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(90deg, red, cyan);
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
-webkit-mask-image: linear-gradient(to bottom, transparent, black);
|
||||
background: linear-gradient(90deg, hotpink, rgb(102, 51, 153));
|
||||
}
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
place-content: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.container-shell {
|
||||
backdrop-filter: blur(5px);
|
||||
background: hsla(0, 0%, 50%, 0.5);
|
||||
padding: 30px 4px 10px 4px;
|
||||
/* border: 2px solid black; */
|
||||
width: auto;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 10px 20px;
|
||||
}
|
||||
|
||||
.container-shell:before {
|
||||
content: "preview powered by jessibuca pro";
|
||||
position: absolute;
|
||||
color: darkgray;
|
||||
top: 4px;
|
||||
left: 10px;
|
||||
text-shadow: 1px 1px black;
|
||||
}
|
||||
|
||||
#container {
|
||||
background: rgba(13, 14, 27, 0.7);
|
||||
width: 960px;
|
||||
height: 597px;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
color: white;
|
||||
place-content: stretch;
|
||||
}
|
||||
|
||||
.input2 {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.input input {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.err {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 10px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.option {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 10px;
|
||||
display: flex;
|
||||
place-content: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.option span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.page {
|
||||
|
||||
/* background-repeat: no-repeat;
|
||||
background-position: top; */
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
#container {
|
||||
width: 90vw;
|
||||
height: 52.7vw;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="page">
|
||||
<div class="root">
|
||||
<div class="container-shell">
|
||||
<div id="container"></div>
|
||||
<div class="input">
|
||||
<div><input type="checkbox" checked id="useMSE" /><span>MediaSource</span>
|
||||
<input type="checkbox" id="useWCS" /><span>Webcodec</span>
|
||||
<input type="checkbox" id="useSIMD" /><span>SIMD</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input">
|
||||
<span>协议切换:</span>
|
||||
<select id="protocol">
|
||||
<option value="hdl">hdl(http-flv)</option>
|
||||
<option value="ws-flv">ws-flv</option>
|
||||
<option value="ws-raw">jessica(ws-raw)</option>
|
||||
<option value="ws-h265">ws-h265</option>
|
||||
<option value="ws-h264">ws-h264</option>
|
||||
<option value="http-h265">http-h265</option>
|
||||
<option value="http-h264">http-h264</option>
|
||||
<option value="fmp4">fmp4</option>
|
||||
<option value="hls">hls</option>
|
||||
<option value="webrtc">webrtc</option>
|
||||
<option value="webtransport">webtransport</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input">
|
||||
<div>
|
||||
<span>缓存时长:</span>
|
||||
<input placeholder="单位:秒" type="text" id="videoBuffer" style="width: 50px" value="0">秒
|
||||
<span>缓存延迟(延迟超过会触发丢帧):</span>
|
||||
<input placeholder="单位:秒" type="text" id="videoBufferDelay" style="width: 50px" value="5">秒
|
||||
<button id="replay">重播</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<div>输入URL:</div>
|
||||
<input autocomplete="on" id="playUrl" value="" />
|
||||
<button id="play">播放</button>
|
||||
<button id="pause" style="display: none">停止</button>
|
||||
</div>
|
||||
<div class="input" style="line-height: 30px">
|
||||
<button id="destroy">销毁</button>
|
||||
<span class="fps-inner"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input">
|
||||
<div>
|
||||
当前浏览器:
|
||||
<span id="mseSupport264" style="color: green;display: none">支持MSE H264解码;</span>
|
||||
<span id="mseSupport" style="color: green;display: none">支持MSE H265解码;</span>
|
||||
<span id="mseNotSupport" style="color: red;display: none">不支持MSE H264解码;</span>
|
||||
<span id="mseNotSupport264" style="color: red;display: none">不支持MSE H265解码,会自动切换成wasm解码;</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input">
|
||||
<div>
|
||||
当前浏览器:
|
||||
<span id="wcsSupport264" style="color: green;display: none">支持Webcodecs H264解码;</span>
|
||||
<span id="wcsSupport" style="color: green;display: none">支持Webcodecs H265解码;</span>
|
||||
<span id="wcsNotSupport264" style="color: red;display: none">不支持Webcodecs H264解码(https/localhost);</span>
|
||||
<span id="wcsNotSupport" style="color: red;display: none">不支持Webcodecs
|
||||
H265解码(https/localhost),会自动切换成wasm解码</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input">
|
||||
<div>
|
||||
当前浏览器:
|
||||
<span id="simdSupport" style="color: green;display: none">支持WASM SIMD解码</span>
|
||||
<span id="simdNotSupport" style="color: red;display: none">不支持WASM SIMD解码,会自动切换成wasm解码</span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function getBrowser() {
|
||||
const UserAgent = window.navigator.userAgent.toLowerCase() || '';
|
||||
let browserInfo = {
|
||||
type: '',
|
||||
version: ''
|
||||
};
|
||||
var browserArray = {
|
||||
IE: window.ActiveXObject || "ActiveXObject" in window, // IE
|
||||
Chrome: UserAgent.indexOf('chrome') > -1 && UserAgent.indexOf('safari') > -1, // Chrome浏览器
|
||||
Firefox: UserAgent.indexOf('firefox') > -1, // 火狐浏览器
|
||||
Opera: UserAgent.indexOf('opera') > -1, // Opera浏览器
|
||||
Safari: UserAgent.indexOf('safari') > -1 && UserAgent.indexOf('chrome') == -1, // safari浏览器
|
||||
Edge: UserAgent.indexOf('edge') > -1, // Edge浏览器
|
||||
QQBrowser: /qqbrowser/.test(UserAgent), // qq浏览器
|
||||
WeixinBrowser: /MicroMessenger/i.test(UserAgent) // 微信浏览器
|
||||
};
|
||||
// console.log(browserArray)
|
||||
for (let i in browserArray) {
|
||||
if (browserArray[i]) {
|
||||
let versions = '';
|
||||
if (i === 'IE') {
|
||||
const versionArray = UserAgent.match(/(msie\s|trident.*rv:)([\w.]+)/);
|
||||
if (versionArray && versionArray.length > 2) {
|
||||
versions = UserAgent.match(/(msie\s|trident.*rv:)([\w.]+)/)[2];
|
||||
}
|
||||
} else if (i === 'Chrome') {
|
||||
for (let mt in navigator.mimeTypes) {
|
||||
//检测是否是360浏览器(测试只有pc端的360才起作用)
|
||||
if (navigator.mimeTypes[mt]['type'] === 'application/360softmgrplugin') {
|
||||
i = '360';
|
||||
}
|
||||
}
|
||||
const versionArray = UserAgent.match(/chrome\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
} else if (i === 'Firefox') {
|
||||
const versionArray = UserAgent.match(/firefox\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
} else if (i === 'Opera') {
|
||||
const versionArray = UserAgent.match(/opera\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
} else if (i === 'Safari') {
|
||||
const versionArray = UserAgent.match(/version\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
} else if (i === 'Edge') {
|
||||
const versionArray = UserAgent.match(/edge\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
} else if (i === 'QQBrowser') {
|
||||
const versionArray = UserAgent.match(/qqbrowser\/([\d.]+)/);
|
||||
if (versionArray && versionArray.length > 1) {
|
||||
versions = versionArray[1];
|
||||
}
|
||||
}
|
||||
browserInfo.type = i;
|
||||
browserInfo.version = parseInt(versions);
|
||||
}
|
||||
}
|
||||
return browserInfo;
|
||||
}
|
||||
|
||||
|
||||
function checkSupportMSEHevc() {
|
||||
return window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="hev1.1.6.L123.b0"');
|
||||
}
|
||||
|
||||
function checkSupportMSEH264() {
|
||||
return window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.64002A"');
|
||||
}
|
||||
|
||||
function checkSupportWCSHevc() {
|
||||
const browserInfo = getBrowser();
|
||||
|
||||
return browserInfo.type.toLowerCase() === 'chrome' && browserInfo.version >= 107 && (location.protocol === 'https:' || location.hostname === 'localhost');
|
||||
}
|
||||
|
||||
function checkSupportWCS() {
|
||||
return "VideoEncoder" in window;
|
||||
}
|
||||
|
||||
|
||||
function checkSupportSIMD() {
|
||||
return WebAssembly && WebAssembly.validate(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 10, 1, 8, 0, 65, 0, 253, 15, 253, 98, 11]));
|
||||
}
|
||||
|
||||
let support = document.getElementById('mseSupport');
|
||||
let notSupport = document.getElementById('mseNotSupport');
|
||||
if (checkSupportMSEHevc()) {
|
||||
support.style.display = 'inline-block';
|
||||
} else {
|
||||
notSupport.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
let supportH264 = document.getElementById('mseSupport264');
|
||||
let notSupportH264 = document.getElementById('mseNotSupport264');
|
||||
if (checkSupportMSEH264()) {
|
||||
supportH264.style.display = 'inline-block';
|
||||
} else {
|
||||
notSupportH264.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
|
||||
let supportWcsHevc = document.getElementById('wcsSupport');
|
||||
let notSupportWcsHevc = document.getElementById('wcsNotSupport');
|
||||
|
||||
if (checkSupportWCSHevc()) {
|
||||
supportWcsHevc.style.display = 'inline-block';
|
||||
} else {
|
||||
notSupportWcsHevc.style.display = 'inline-block';
|
||||
}
|
||||
let supportWcs = document.getElementById('wcsSupport264');
|
||||
let notSupportWcs = document.getElementById('wcsNotSupport264');
|
||||
if (checkSupportWCS()) {
|
||||
supportWcs.style.display = 'inline-block';
|
||||
} else {
|
||||
notSupportWcs.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
|
||||
let supportSimd = document.getElementById('simdSupport');
|
||||
let notSupportSimd = document.getElementById('simdNotSupport');
|
||||
|
||||
if (checkSupportSIMD()) {
|
||||
supportSimd.style.display = 'inline-block';
|
||||
} else {
|
||||
notSupportSimd.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var $player = document.getElementById('play');
|
||||
var $pause = document.getElementById('pause');
|
||||
var $playHref = document.getElementById('playUrl');
|
||||
var $container = document.getElementById('container');
|
||||
var $destroy = document.getElementById('destroy');
|
||||
var $useMSE = document.getElementById('useMSE');
|
||||
var $useSIMD = document.getElementById('useSIMD');
|
||||
var $useWCS = document.getElementById('useWCS');
|
||||
var $videoBuffer = document.getElementById('videoBuffer');
|
||||
var $videoBufferDelay = document.getElementById('videoBufferDelay');
|
||||
var $replay = document.getElementById('replay');
|
||||
var $fps = document.querySelector('.fps-inner');
|
||||
var $protocol = document.getElementById('protocol');
|
||||
var showOperateBtns = true; // 是否显示按钮
|
||||
var forceNoOffscreen = true; //
|
||||
var jessibuca = null;
|
||||
|
||||
function isMobile() {
|
||||
return (/iphone|ipad|android.*mobile|windows.*phone|blackberry.*mobile/i.test(window.navigator.userAgent.toLowerCase()));
|
||||
}
|
||||
|
||||
function isPad() {
|
||||
return (/ipad|android(?!.*mobile)|tablet|kindle|silk/i.test(window.navigator.userAgent.toLowerCase()));
|
||||
}
|
||||
|
||||
const useVconsole = isMobile() || isPad();
|
||||
|
||||
if (useVconsole && window.VConsole) {
|
||||
new window.VConsole();
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(location.search);
|
||||
const isHttps = location.protocol.startsWith("https");
|
||||
const type = query.get('type') || 'hdl';
|
||||
$protocol.value = type;
|
||||
let pluginName = type;
|
||||
let ext = "." + type;
|
||||
switch (type) {
|
||||
case 'hdl':
|
||||
ext = '.flv';
|
||||
break;
|
||||
case 'ws-flv':
|
||||
ext = '.flv';
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'ws-raw':
|
||||
ext = "";
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'ws-h265':
|
||||
ext = '.h265';
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'ws-h264':
|
||||
ext = '.h264';
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'http-h265':
|
||||
ext = '.h265';
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'http-h264':
|
||||
ext = '.h264';
|
||||
pluginName = 'jessica';
|
||||
break;
|
||||
case 'fmp4':
|
||||
ext = '.mp4';
|
||||
break;
|
||||
case 'hls':
|
||||
ext = '.m3u8';
|
||||
break;
|
||||
}
|
||||
$playHref.value = (type.startsWith('ws') ? (isHttps ? "wss://" : "ws://") + location.host : location.origin) + location.pathname.replace('preview', pluginName) + ext;
|
||||
switch (type) {
|
||||
case 'webrtc':
|
||||
$playHref.value = 'webrtc://' + location.host + location.pathname.replace('preview', pluginName + '/play');
|
||||
break;
|
||||
case 'webtransport':
|
||||
$playHref.value = 'wt://' + location.hostname + ':4433' + location.pathname.replace('preview', 'play');
|
||||
break;
|
||||
}
|
||||
function create() {
|
||||
jessibuca = new JessibucaPro({
|
||||
container: $container,
|
||||
videoBuffer: Number($videoBuffer.value), // 缓存时长
|
||||
videoBufferDelay: Number($videoBufferDelay.value), // 1000s
|
||||
isResize: false,
|
||||
text: "",
|
||||
loadingText: "加载中",
|
||||
debug: true,
|
||||
debugLevel: "debug",
|
||||
useMSE: $useMSE.checked === true,
|
||||
useSIMD: $useSIMD.checked === true,
|
||||
useWCS: $useWCS.checked === true,
|
||||
showBandwidth: showOperateBtns, // 显示网速
|
||||
showPerformance: showOperateBtns, // 显示性能
|
||||
operateBtns: {
|
||||
fullscreen: showOperateBtns,
|
||||
screenshot: showOperateBtns,
|
||||
play: showOperateBtns,
|
||||
audio: showOperateBtns,
|
||||
ptz: showOperateBtns,
|
||||
quality: showOperateBtns,
|
||||
performance: showOperateBtns,
|
||||
},
|
||||
heartTimeoutReplayUseLastFrameShow: true,
|
||||
audioEngine: "worklet",
|
||||
qualityConfig: ['普清', '高清', '超清', '4K', '8K'],
|
||||
forceNoOffscreen: forceNoOffscreen,
|
||||
isNotMute: false,
|
||||
heartTimeout: 10,
|
||||
// isFlv: true
|
||||
},);
|
||||
|
||||
|
||||
jessibuca.on('ptz', (arrow) => {
|
||||
console.log('ptz', arrow);
|
||||
});
|
||||
|
||||
jessibuca.on('streamQualityChange', (value) => {
|
||||
console.log('streamQualityChange', value);
|
||||
});
|
||||
|
||||
jessibuca.on('timeUpdate', (value) => {
|
||||
// console.log('timeUpdate', value);
|
||||
});
|
||||
|
||||
jessibuca.on('stats', (stats) => {
|
||||
// console.log('stats', stats);
|
||||
$fps.textContent = `FPS: ${stats.fps} DFPS: ${stats.dfps}`;
|
||||
});
|
||||
|
||||
jessibuca.on(JessibucaPro.EVENTS.crashLog, (log) => {
|
||||
console.log('crashLog', log);
|
||||
});
|
||||
|
||||
|
||||
$player.style.display = 'inline-block';
|
||||
$pause.style.display = 'none';
|
||||
$destroy.style.display = 'none';
|
||||
$fps.textContent = '';
|
||||
}
|
||||
|
||||
|
||||
create();
|
||||
|
||||
function play() {
|
||||
var href = $playHref.value;
|
||||
if (href) {
|
||||
jessibuca.play(href);
|
||||
$player.style.display = 'none';
|
||||
$pause.style.display = 'inline-block';
|
||||
$destroy.style.display = 'inline-block';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function replay() {
|
||||
if (jessibuca) {
|
||||
jessibuca.destroy().then(() => {
|
||||
create();
|
||||
play();
|
||||
});
|
||||
} else {
|
||||
create();
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
$replay.addEventListener('click', function () {
|
||||
replay();
|
||||
});
|
||||
|
||||
$player.addEventListener('click', function () {
|
||||
play();
|
||||
}, false);
|
||||
|
||||
|
||||
$pause.addEventListener('click', function () {
|
||||
$player.style.display = 'inline-block';
|
||||
$pause.style.display = 'none';
|
||||
$fps.textContent = '';
|
||||
jessibuca.pause();
|
||||
});
|
||||
|
||||
$destroy.addEventListener('click', function () {
|
||||
if (jessibuca) {
|
||||
jessibuca.destroy().then(() => {
|
||||
create();
|
||||
});
|
||||
} else {
|
||||
create();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$useMSE.addEventListener('click', function () {
|
||||
const checked = $useMSE.checked;
|
||||
if (checked) {
|
||||
$useSIMD.checked = false;
|
||||
$useWCS.checked = false;
|
||||
}
|
||||
replay();
|
||||
});
|
||||
|
||||
$useSIMD.addEventListener('click', function () {
|
||||
const checked = $useSIMD.checked;
|
||||
if (checked) {
|
||||
$useMSE.checked = false;
|
||||
$useWCS.checked = false;
|
||||
}
|
||||
replay();
|
||||
});
|
||||
|
||||
$useWCS.addEventListener('click', function () {
|
||||
const checked = $useWCS.checked;
|
||||
if (checked) {
|
||||
$useMSE.checked = false;
|
||||
$useSIMD.checked = false;
|
||||
}
|
||||
replay();
|
||||
});
|
||||
|
||||
$protocol.addEventListener('change', function () {
|
||||
if ($protocol.value === 'webtransport')
|
||||
location.replace('https://local.monibuca.com:8081' + location.pathname + '?type=' + $protocol.value);
|
||||
else
|
||||
location.replace(location.origin + location.pathname + '?type=' + $protocol.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>M7s Preview 预览</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="javascript:void 0" id="unmute">解除静音</a>
|
||||
<script src="jessibuca-pro-preview.js"></script>
|
||||
<script>
|
||||
(function(){
|
||||
var ctx = new AudioContext();
|
||||
if(ctx.state == "running"){
|
||||
document.getElementById("unmute").style.display = "none";
|
||||
} else {
|
||||
ctx.onstatechange = ()=> {
|
||||
if(ctx.state == 'running'){
|
||||
document.getElementById("unmute").style.display = "none";
|
||||
}
|
||||
}}
|
||||
})()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user