Added handbreak cli conversion, fixed background loading, cleanup
This commit is contained in:
parent
f5d2f3dd4f
commit
4b3782d671
|
@ -162,18 +162,11 @@ def _get_stream(video_path=None, stream_target=None):
|
|||
# Yes, the process probably should give us info we can process when failure occures.
|
||||
command = [
|
||||
"ffmpeg", "-nostdin", "-fflags", "+genpts", "-hwaccel", "cuda",
|
||||
# --preset ultrafast --threads 1
|
||||
"-stream_loop", "1", "-i", video_path, "-strict", "experimental",
|
||||
"-stream_loop", "-1", "-i", video_path, "-strict", "experimental",
|
||||
"-vcodec", "copy", "-acodec", "copy", "-f", "rtsp",
|
||||
"-rtsp_transport", "tcp", stream_target
|
||||
]
|
||||
|
||||
# command = [
|
||||
# "ffmpeg", "-nostdin", "-fflags", "+genpts", "-i", video_path,
|
||||
# "-strict", "experimental", "-f",
|
||||
# "rtsp", "-rtsp_transport", "udp", stream_target
|
||||
# ]
|
||||
|
||||
proc = subprocess.Popen(command, shell=False, stdin=None, stdout=None, stderr=None)
|
||||
window = window_controllers[ session["win_controller_id"] ].get_window_by_index(0)
|
||||
tab = window.get_tab_by_index(0)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# Python imports
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Lib imports
|
||||
from flask import Flask
|
||||
|
|
|
@ -133,25 +133,22 @@ def remux_video(sse_id, hash, path, view):
|
|||
link = f"https://www.webfm.com/sse/{sse_id}"
|
||||
body = '{"path":"static/remuxs/' + hash + '.mp4"}'
|
||||
|
||||
good_result = view.remux_video(hash, path)
|
||||
# good_result = view.remux_video(hash, path)
|
||||
good_result = view.handbrake_remux_video(hash, path)
|
||||
if not good_result:
|
||||
body = json_message.create("warning", "Remuxing: Remux failed...")
|
||||
|
||||
requests.post(link, data=body, timeout=10)
|
||||
|
||||
|
||||
# @daemon_threaded
|
||||
def setup_stream(sse_id, hash, path):
|
||||
link = f"https://www.webfm.com/sse/{sse_id}"
|
||||
_sub_uuid = uuid.uuid4().hex
|
||||
_video_path = path
|
||||
_stub = f"{hash}{_sub_uuid}"
|
||||
_rtsp_path = f"rtsp://www.{app_name.lower()}.com:8554/{_stub}"
|
||||
_rtmp_path = f"rtmp://www.{app_name.lower()}.com:1935/{_stub}"
|
||||
_hls_path = f"http://www.{app_name.lower()}.com:8888/{_stub}/"
|
||||
_rtsp_path = f"rtsp://127.0.0.1:8554/{_stub}"
|
||||
_webrtc_path = f"http://www.{app_name.lower()}.com:8889/{_stub}/"
|
||||
_stream_target = _rtsp_path
|
||||
body = '{"stream":"' + _stream_target + '"}'
|
||||
|
||||
process = get_stream()
|
||||
if process:
|
||||
|
@ -168,6 +165,8 @@ def setup_stream(sse_id, hash, path):
|
|||
requests.post(link, data=body, timeout=10)
|
||||
return
|
||||
|
||||
_stream_target = _webrtc_path
|
||||
body = '{"stream":"' + _stream_target + '"}'
|
||||
requests.post(link, data=body, timeout=10)
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ eventSource.onmessage = (eve) => {
|
|||
try {
|
||||
const data = JSON.parse(eve.data);
|
||||
const sse_msg = JSON.parse(data.message);
|
||||
|
||||
if (sse_msg.hasOwnProperty('path') || sse_msg.hasOwnProperty('stream')) {
|
||||
const target = (sse_msg.path) ? sse_msg.path : sse_msg.stream;
|
||||
handleMedia(target);
|
||||
|
|
|
@ -70,22 +70,21 @@ const closeFile = async () => {
|
|||
}
|
||||
|
||||
const showFile = async (title, hash, extension, type, target=null) => {
|
||||
document.getElementById("selectedFile").innerText = title;
|
||||
document.getElementById("image-viewer").style.display = "none";
|
||||
document.getElementById("text-viewer").style.display = "none";
|
||||
document.getElementById("pdf-viewer").style.display = "none";
|
||||
document.getElementById("video_container").style.display = "none";
|
||||
document.getElementById("trailerPlayer").style.display = "none";
|
||||
|
||||
let titleElm = document.getElementById("selectedFile");
|
||||
titleElm.innerText = title;
|
||||
|
||||
// FIXME: Yes, a wasted call every time there is no stream.
|
||||
await fetchData("api/stop-current-stream");
|
||||
|
||||
if (type === "video" || type === "stream") {
|
||||
isStream = (type === "stream") ? true : false;
|
||||
target = (type === "stream") ? "stream" : "remux";
|
||||
setupVideo(hash, extension, isStream, target);
|
||||
action = (type === "stream") ? "stream" : "remux";
|
||||
setupVideo(hash, extension, isStream, action);
|
||||
setSelectedActiveMedia(target);
|
||||
} else if (type === "trailer") {
|
||||
launchTrailer(hash);
|
||||
|
@ -103,7 +102,7 @@ const launchTrailer = (link) => {
|
|||
modal.show();
|
||||
}
|
||||
|
||||
const setupVideo = async (hash, extension, isStream, target="remux") => {
|
||||
const setupVideo = async (hash, extension, isStream, action="remux") => {
|
||||
document.getElementById("video_container").style.display = "";
|
||||
video_path = `api/file-manager-action/files/${hash}`;
|
||||
|
||||
|
@ -120,7 +119,7 @@ const setupVideo = async (hash, extension, isStream, target="remux") => {
|
|||
return;
|
||||
}
|
||||
|
||||
const data = await fetchData(`api/file-manager-action/${target}/${hash}`);
|
||||
const data = await fetchData(`api/file-manager-action/${action}/${hash}`);
|
||||
displayMessage(data.message.text, data.message.type, 5);
|
||||
} catch (e) {
|
||||
video.style.display = "none";
|
||||
|
@ -236,8 +235,10 @@ const loadBackgroundPoster = () => {
|
|||
}
|
||||
|
||||
if (data.poster !== null) {
|
||||
background_image = "api/file-manager-action/files/000.jpg?d=" + Date.now();
|
||||
updateBackground(background_image, false);
|
||||
getSHA256Hash("000.jpg").then((_hash) => {
|
||||
background_image = "api/file-manager-action/files/" + _hash + "?d=" + Date.now();
|
||||
updateBackground(background_image, false);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -377,3 +378,12 @@ const clearCache = () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getSHA256Hash = async (input) => {
|
||||
const textAsBuffer = new TextEncoder().encode(input);
|
||||
const hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const hash = hashArray.map((item) => item.toString(16).padStart(2, "0")).join("");
|
||||
|
||||
return hash.substring(0, 18);
|
||||
};
|
||||
|
|
|
@ -100,7 +100,7 @@ authMethods: [basic, digest]
|
|||
# RTMP parameters
|
||||
|
||||
# Disable support for the RTMP protocol.
|
||||
rtmpDisable: no
|
||||
rtmpDisable: yes
|
||||
# Address of the RTMP listener. This is needed only when encryption is "no" or "optional".
|
||||
rtmpAddress: :1935
|
||||
# Encrypt connections with TLS (RTMPS).
|
||||
|
@ -120,12 +120,12 @@ rtmpServerCert: server.crt
|
|||
# HLS parameters
|
||||
|
||||
# Disable support for the HLS protocol.
|
||||
hlsDisable: no
|
||||
hlsDisable: yes
|
||||
# Address of the HLS listener.
|
||||
hlsAddress: :8888
|
||||
# Enable TLS/HTTPS on the HLS server.
|
||||
# This is required for Low-Latency HLS.
|
||||
hlsEncryption: yes
|
||||
hlsEncryption: no
|
||||
# Path to the server key. This is needed only when encryption is yes.
|
||||
# This can be generated with:
|
||||
# openssl genrsa -out server.key 2048
|
||||
|
@ -135,22 +135,22 @@ hlsServerKey: server.key
|
|||
hlsServerCert: server.crt
|
||||
# By default, HLS is generated only when requested by a user.
|
||||
# This option allows to generate it always, avoiding the delay between request and generation.
|
||||
hlsAlwaysRemux: yes
|
||||
hlsAlwaysRemux: no
|
||||
# Variant of the HLS protocol to use. Available options are:
|
||||
# * mpegts - uses MPEG-TS segments, for maximum compatibility.
|
||||
# * fmp4 - uses fragmented MP4 segments, more efficient.
|
||||
# * lowLatency - uses Low-Latency HLS.
|
||||
hlsVariant: lowLatency
|
||||
hlsVariant: mpegts
|
||||
# Number of HLS segments to keep on the server.
|
||||
# Segments allow to seek through the stream.
|
||||
# Their number doesn't influence latency.
|
||||
hlsSegmentCount: 7
|
||||
hlsSegmentCount: 24
|
||||
# Minimum duration of each segment.
|
||||
# A player usually puts 3 segments in a buffer before reproducing the stream.
|
||||
# The final segment duration is also influenced by the interval between IDR frames,
|
||||
# since the server changes the duration in order to include at least one IDR frame
|
||||
# in each segment.
|
||||
hlsSegmentDuration: 1s
|
||||
hlsSegmentDuration: 5s
|
||||
# Minimum duration of each part.
|
||||
# A player usually puts 3 parts in a buffer before reproducing the stream.
|
||||
# Parts are used in Low-Latency HLS in place of segments.
|
||||
|
@ -166,13 +166,13 @@ hlsAllowOrigin: '*'
|
|||
# List of IPs or CIDRs of proxies placed before the HLS server.
|
||||
# If the server receives a request from one of these entries, IP in logs
|
||||
# will be taken from the X-Forwarded-For header.
|
||||
hlsTrustedProxies: []
|
||||
hlsTrustedProxies: [0.0.0.0]
|
||||
|
||||
###############################################
|
||||
# WebRTC parameters
|
||||
|
||||
# Disable support for the WebRTC protocol.
|
||||
webrtcDisable: yes
|
||||
webrtcDisable: no
|
||||
# Address of the WebRTC listener.
|
||||
webrtcAddress: :8889
|
||||
# Enable TLS/HTTPS on the WebRTC server.
|
||||
|
@ -190,7 +190,7 @@ webrtcAllowOrigin: '*'
|
|||
# List of IPs or CIDRs of proxies placed before the WebRTC server.
|
||||
# If the server receives a request from one of these entries, IP in logs
|
||||
# will be taken from the X-Forwarded-For header.
|
||||
webrtcTrustedProxies: []
|
||||
webrtcTrustedProxies: [0.0.0.0, 127.0.0.1]
|
||||
# List of ICE servers, in format type:user:pass:host:port or type:host:port.
|
||||
# type can be "stun", "turn" or "turns".
|
||||
# STUN servers are used to get the public IP of both server and clients.
|
||||
|
@ -200,7 +200,7 @@ webrtcTrustedProxies: []
|
|||
webrtcICEServers: [stun:stun.l.google.com:19302, stun:stun.services.mozilla.com]
|
||||
# List of public IP addresses that are to be used as a host.
|
||||
# This is used typically for servers that are behind 1:1 D-NAT.
|
||||
webrtcICEHostNAT1To1IPs: []
|
||||
webrtcICEHostNAT1To1IPs: [0.0.0.0]
|
||||
# Address of a ICE UDP listener in format host:port.
|
||||
# If filled, ICE traffic will come through a single UDP port,
|
||||
# allowing the deployment of the server inside a container or behind a NAT.
|
||||
|
|
|
@ -8,6 +8,9 @@ import shlex
|
|||
# Apoplication imports
|
||||
|
||||
|
||||
class ShellFMLauncherException(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
class Launcher:
|
||||
|
@ -76,7 +79,24 @@ class Launcher:
|
|||
try:
|
||||
proc = subprocess.Popen(command)
|
||||
proc.wait()
|
||||
except Exception as e:
|
||||
except ShellFMLauncherException as e:
|
||||
self.logger.debug(e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def handbrake_remux_video(self, hash, file):
|
||||
remux_vid_pth = f"{self.REMUX_FOLDER}/{hash}.mp4"
|
||||
self.logger.debug(remux_vid_pth)
|
||||
|
||||
if not os.path.isfile(remux_vid_pth):
|
||||
self.check_remux_space()
|
||||
|
||||
command = ["HandBrakeCLI", "-i", file, "-e", "nvenc_h264", "-f", "av_mp4", "-O", "-o", remux_vid_pth]
|
||||
try:
|
||||
proc = subprocess.Popen(command)
|
||||
proc.wait()
|
||||
except ShellFMLauncherException as e:
|
||||
self.logger.debug(e)
|
||||
return False
|
||||
|
||||
|
@ -86,7 +106,7 @@ class Launcher:
|
|||
limit = self.remux_folder_max_disk_usage
|
||||
try:
|
||||
limit = int(limit)
|
||||
except Exception as e:
|
||||
except ShellFMLauncherException as e:
|
||||
self.logger.debug(e)
|
||||
return
|
||||
|
||||
|
|
Loading…
Reference in New Issue