mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-02-01 10:31:54 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -35,11 +35,11 @@ export function Streamer() {
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
var __janus_enabled = null;
|
||||
var __janus_imported = null;
|
||||
var __streamer = null;
|
||||
|
||||
var __state = null;
|
||||
var __resolution = {"width": 640, "height": 480};
|
||||
var __res = {"width": 640, "height": 480};
|
||||
|
||||
var __init__ = function() {
|
||||
__streamer = new MjpegStreamer(__setActive, __setInactive, __setInfo);
|
||||
@@ -47,22 +47,22 @@ export function Streamer() {
|
||||
$("stream-led").title = "Stream inactive";
|
||||
|
||||
tools.slider.setParams($("stream-quality-slider"), 5, 100, 5, 80, function(value) {
|
||||
$("stream-quality-value").innerHTML = `${value}%`;
|
||||
$("stream-quality-value").innerText = `${value}%`;
|
||||
});
|
||||
tools.slider.setOnUpDelayed($("stream-quality-slider"), 1000, (value) => __sendParam("quality", value));
|
||||
|
||||
tools.slider.setParams($("stream-h264-bitrate-slider"), 25, 20000, 25, 5000, function(value) {
|
||||
$("stream-h264-bitrate-value").innerHTML = value;
|
||||
$("stream-h264-bitrate-value").innerText = value;
|
||||
});
|
||||
tools.slider.setOnUpDelayed($("stream-h264-bitrate-slider"), 1000, (value) => __sendParam("h264_bitrate", value));
|
||||
|
||||
tools.slider.setParams($("stream-h264-gop-slider"), 0, 60, 1, 30, function(value) {
|
||||
$("stream-h264-gop-value").innerHTML = value;
|
||||
$("stream-h264-gop-value").innerText = value;
|
||||
});
|
||||
tools.slider.setOnUpDelayed($("stream-h264-gop-slider"), 1000, (value) => __sendParam("h264_gop", value));
|
||||
|
||||
tools.slider.setParams($("stream-desired-fps-slider"), 0, 120, 1, 0, function(value) {
|
||||
$("stream-desired-fps-value").innerHTML = (value === 0 ? "Unlimited" : value);
|
||||
$("stream-desired-fps-value").innerText = (value === 0 ? "Unlimited" : value);
|
||||
});
|
||||
tools.slider.setOnUpDelayed($("stream-desired-fps-slider"), 1000, (value) => __sendParam("desired_fps", value));
|
||||
|
||||
@@ -86,7 +86,7 @@ export function Streamer() {
|
||||
tools.slider.setParams($("stream-audio-volume-slider"), 0, 100, 1, 0, function(value) {
|
||||
$("stream-video").muted = !value;
|
||||
$("stream-video").volume = value / 100;
|
||||
$("stream-audio-volume-value").innerHTML = value + "%";
|
||||
$("stream-audio-volume-value").innerText = value + "%";
|
||||
if (__streamer.getMode() === "janus") {
|
||||
let allow_audio = !$("stream-video").muted;
|
||||
if (__streamer.isAudioAllowed() !== allow_audio) {
|
||||
@@ -110,6 +110,13 @@ export function Streamer() {
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
self.ensureDeps = function(callback) {
|
||||
JanusStreamer.ensure_janus(function(avail) {
|
||||
__janus_imported = avail;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
self.getGeometry = function() {
|
||||
// Первоначально обновление геометрии считалось через ResizeObserver.
|
||||
// Но оно не ловило некоторые события, например в последовательности:
|
||||
@@ -132,90 +139,103 @@ export function Streamer() {
|
||||
};
|
||||
};
|
||||
|
||||
self.setJanusEnabled = function(enabled) {
|
||||
let has_webrtc = JanusStreamer.is_webrtc_available();
|
||||
let has_h264 = JanusStreamer.is_h264_available();
|
||||
|
||||
let set_enabled = function(imported) {
|
||||
tools.hidden.setVisible($("stream-message-no-webrtc"), enabled && !has_webrtc);
|
||||
tools.hidden.setVisible($("stream-message-no-h264"), enabled && !has_h264);
|
||||
__janus_enabled = (enabled && has_webrtc && imported); // Don't check has_h264 for sure
|
||||
tools.feature.setEnabled($("stream-mode"), __janus_enabled);
|
||||
tools.info(
|
||||
`Stream: Janus WebRTC state: enabled=${enabled},`
|
||||
+ ` webrtc=${has_webrtc}, h264=${has_h264}, imported=${imported}`
|
||||
);
|
||||
let mode = (__janus_enabled ? tools.storage.get("stream.mode", "janus") : "mjpeg");
|
||||
tools.radio.clickValue("stream-mode-radio", mode);
|
||||
if (!__janus_enabled) {
|
||||
tools.feature.setEnabled($("stream-audio"), false); // Enabling in stream_janus.js
|
||||
}
|
||||
self.setState(__state);
|
||||
};
|
||||
|
||||
if (enabled && has_webrtc) {
|
||||
JanusStreamer.ensure_janus(set_enabled);
|
||||
} else {
|
||||
set_enabled(false);
|
||||
}
|
||||
};
|
||||
|
||||
self.setState = function(state) {
|
||||
__state = state;
|
||||
if (__janus_enabled !== null) {
|
||||
__applyState(wm.isWindowVisible($("stream-window")) ? __state : null);
|
||||
if (state) {
|
||||
if (!__state) {
|
||||
__state = {};
|
||||
}
|
||||
if (state.features !== undefined) {
|
||||
__state.features = state.features;
|
||||
__state.limits = state.limits; // Following together with features
|
||||
}
|
||||
if (__state.features !== undefined && state.streamer !== undefined) {
|
||||
__state.streamer = state.streamer;
|
||||
__setControlsEnabled(!!state.streamer);
|
||||
}
|
||||
} else {
|
||||
__state = null;
|
||||
__setControlsEnabled(false);
|
||||
}
|
||||
let visible = wm.isWindowVisible($("stream-window"));
|
||||
__applyState((visible && __state && __state.features) ? state : null);
|
||||
};
|
||||
|
||||
var __applyState = function(state) {
|
||||
if (state) {
|
||||
tools.feature.setEnabled($("stream-quality"), state.features.quality && (state.streamer === null || state.streamer.encoder.quality > 0));
|
||||
tools.feature.setEnabled($("stream-h264-bitrate"), state.features.h264 && __janus_enabled);
|
||||
tools.feature.setEnabled($("stream-h264-gop"), state.features.h264 && __janus_enabled);
|
||||
tools.feature.setEnabled($("stream-resolution"), state.features.resolution);
|
||||
if (__janus_imported === null) {
|
||||
alert("__janus_imported is null, please report");
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.streamer) {
|
||||
tools.el.setEnabled($("stream-quality-slider"), true);
|
||||
tools.slider.setValue($("stream-quality-slider"), state.streamer.encoder.quality);
|
||||
if (!state) {
|
||||
__streamer.stopStream();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.features.h264 && __janus_enabled) {
|
||||
__setLimitsAndValue($("stream-h264-bitrate-slider"), state.limits.h264_bitrate, state.streamer.h264.bitrate);
|
||||
tools.el.setEnabled($("stream-h264-bitrate-slider"), true);
|
||||
if (state.features) {
|
||||
let f = state.features;
|
||||
let l = state.limits;
|
||||
let has_webrtc = JanusStreamer.is_webrtc_available();
|
||||
let has_h264 = JanusStreamer.is_h264_available();
|
||||
let has_janus = (__janus_imported && f.h264 && has_webrtc); // Don't check has_h264 for sure
|
||||
|
||||
__setLimitsAndValue($("stream-h264-gop-slider"), state.limits.h264_gop, state.streamer.h264.gop);
|
||||
tools.el.setEnabled($("stream-h264-gop-slider"), true);
|
||||
tools.info(
|
||||
`Stream: Janus WebRTC state: features.h264=${f.h264},`
|
||||
+ ` webrtc=${has_webrtc}, h264=${has_h264}, janus_imported=${__janus_imported}`
|
||||
);
|
||||
|
||||
tools.hidden.setVisible($("stream-message-no-webrtc"), __janus_imported && f.h264 && !has_webrtc);
|
||||
tools.hidden.setVisible($("stream-message-no-h264"), __janus_imported && f.h264 && !has_h264);
|
||||
|
||||
tools.slider.setRange($("stream-desired-fps-slider"), l.desired_fps.min, l.desired_fps.max);
|
||||
if (f.resolution) {
|
||||
let el = $("stream-resolution-selector");
|
||||
el.options.length = 0;
|
||||
for (let res of l.available_resolutions) {
|
||||
tools.selector.addOption(el, res, res);
|
||||
}
|
||||
|
||||
__setLimitsAndValue($("stream-desired-fps-slider"), state.limits.desired_fps, state.streamer.source.desired_fps);
|
||||
tools.el.setEnabled($("stream-desired-fps-slider"), true);
|
||||
|
||||
let resolution_str = __makeStringResolution(state.streamer.source.resolution);
|
||||
if (__makeStringResolution(__resolution) !== resolution_str) {
|
||||
__resolution = state.streamer.source.resolution;
|
||||
}
|
||||
|
||||
if (state.features.resolution) {
|
||||
let el = $("stream-resolution-selector");
|
||||
if (!state.limits.available_resolutions.includes(resolution_str)) {
|
||||
state.limits.available_resolutions.push(resolution_str);
|
||||
}
|
||||
tools.selector.setValues(el, state.limits.available_resolutions);
|
||||
tools.selector.setSelectedValue(el, resolution_str);
|
||||
tools.el.setEnabled(el, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
tools.el.setEnabled($("stream-quality-slider"), false);
|
||||
tools.el.setEnabled($("stream-h264-bitrate-slider"), false);
|
||||
tools.el.setEnabled($("stream-h264-gop-slider"), false);
|
||||
tools.el.setEnabled($("stream-desired-fps-slider"), false);
|
||||
tools.el.setEnabled($("stream-resolution-selector"), false);
|
||||
$("stream-resolution-selector").options.length = 0;
|
||||
}
|
||||
if (has_janus) {
|
||||
tools.slider.setRange($("stream-h264-bitrate-slider"), l.h264_bitrate.min, l.h264_bitrate.max);
|
||||
tools.slider.setRange($("stream-h264-gop-slider"), l.h264_gop.min, l.h264_gop.max);
|
||||
}
|
||||
|
||||
__streamer.ensureStream(state.streamer);
|
||||
// tools.feature.setEnabled($("stream-quality"), f.quality); // Only on s.encoder.quality
|
||||
tools.feature.setEnabled($("stream-resolution"), f.resolution);
|
||||
tools.feature.setEnabled($("stream-h264-bitrate"), has_janus);
|
||||
tools.feature.setEnabled($("stream-h264-gop"), has_janus);
|
||||
tools.feature.setEnabled($("stream-mode"), has_janus);
|
||||
if (!has_janus) {
|
||||
tools.feature.setEnabled($("stream-audio"), false);
|
||||
}
|
||||
|
||||
} else {
|
||||
__streamer.stopStream();
|
||||
let mode = (has_janus ? tools.storage.get("stream.mode", "janus") : "mjpeg");
|
||||
tools.radio.clickValue("stream-mode-radio", mode);
|
||||
}
|
||||
|
||||
if (state.streamer) {
|
||||
let s = state.streamer;
|
||||
__res = s.source.resolution;
|
||||
|
||||
{
|
||||
let res = `${__res.width}x${__res.height}`;
|
||||
let el = $("stream-resolution-selector");
|
||||
if (!tools.selector.hasValue(el, res)) {
|
||||
tools.selector.addOption(el, res, res);
|
||||
}
|
||||
el.value = res;
|
||||
}
|
||||
tools.slider.setValue($("stream-quality-slider"), Math.max(s.encoder.quality, 1));
|
||||
tools.slider.setValue($("stream-desired-fps-slider"), s.source.desired_fps);
|
||||
if (s.h264 && s.h264.bitrate) {
|
||||
tools.slider.setValue($("stream-h264-bitrate-slider"), s.h264.bitrate);
|
||||
tools.slider.setValue($("stream-h264-gop-slider"), s.h264.gop); // Following together with gop
|
||||
}
|
||||
|
||||
tools.feature.setEnabled($("stream-quality"), (s.encoder.quality > 0));
|
||||
|
||||
__streamer.ensureStream(s);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -229,16 +249,24 @@ export function Streamer() {
|
||||
$("stream-led").title = "Stream inactive";
|
||||
};
|
||||
|
||||
var __setControlsEnabled = function(enabled) {
|
||||
tools.el.setEnabled($("stream-quality-slider"), enabled);
|
||||
tools.el.setEnabled($("stream-desired-fps-slider"), enabled);
|
||||
tools.el.setEnabled($("stream-resolution-selector"), enabled);
|
||||
tools.el.setEnabled($("stream-h264-bitrate-slider"), enabled);
|
||||
tools.el.setEnabled($("stream-h264-gop-slider"), enabled);
|
||||
};
|
||||
|
||||
var __setInfo = function(is_active, online, text) {
|
||||
$("stream-box").classList.toggle("stream-box-offline", !online);
|
||||
let el_grab = document.querySelector("#stream-window-header .window-grab");
|
||||
let el_info = $("stream-info");
|
||||
let title = `${__streamer.getName()} – `;
|
||||
let title = `${__streamer.getName()} - `;
|
||||
if (is_active) {
|
||||
if (!online) {
|
||||
title += "No signal / ";
|
||||
}
|
||||
title += __makeStringResolution(__resolution);
|
||||
title += `${__res.width}x${__res.height}`;
|
||||
if (text.length > 0) {
|
||||
title += " / " + text;
|
||||
}
|
||||
@@ -249,12 +277,7 @@ export function Streamer() {
|
||||
title += "Inactive";
|
||||
}
|
||||
}
|
||||
el_grab.innerHTML = el_info.innerHTML = title;
|
||||
};
|
||||
|
||||
var __setLimitsAndValue = function(el, limits, value) {
|
||||
tools.slider.setRange(el, limits.min, limits.max);
|
||||
tools.slider.setValue(el, value);
|
||||
el_grab.innerText = el_info.innerText = title;
|
||||
};
|
||||
|
||||
var __resetStream = function(mode=null) {
|
||||
@@ -274,7 +297,7 @@ export function Streamer() {
|
||||
tools.feature.setEnabled($("stream-audio"), false); // Enabling in stream_janus.js
|
||||
}
|
||||
if (wm.isWindowVisible($("stream-window"))) {
|
||||
__streamer.ensureStream(__state ? __state.streamer : null);
|
||||
__streamer.ensureStream((__state && __state.streamer !== undefined) ? __state.streamer : null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -298,12 +321,12 @@ export function Streamer() {
|
||||
};
|
||||
|
||||
var __clickResetButton = function() {
|
||||
wm.confirm("Are you sure you want to reset stream?").then(function (ok) {
|
||||
wm.confirm("Are you sure you want to reset stream?").then(function(ok) {
|
||||
if (ok) {
|
||||
__resetStream();
|
||||
tools.httpPost("/api/streamer/reset", function(http) {
|
||||
tools.httpPost("/api/streamer/reset", null, function(http) {
|
||||
if (http.status !== 200) {
|
||||
wm.error("Can't reset stream:<br>", http.responseText);
|
||||
wm.error("Can't reset stream", http.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -382,16 +405,12 @@ export function Streamer() {
|
||||
};
|
||||
|
||||
var __sendParam = function(name, value) {
|
||||
tools.httpPost(`/api/streamer/set_params?${name}=${value}`, function(http) {
|
||||
tools.httpPost("/api/streamer/set_params", {[name]: value}, function(http) {
|
||||
if (http.status !== 200) {
|
||||
wm.error("Can't configure stream:<br>", http.responseText);
|
||||
wm.error("Can't configure stream", http.responseText);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var __makeStringResolution = function(resolution) {
|
||||
return `${resolution.width}x${resolution.height}`;
|
||||
};
|
||||
|
||||
__init__();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user