1
0
mirror of https://github.com/fHDHR/fHDHR_NextPVR.git synced 2025-12-06 13:06:59 -05:00
fHDHR_NextPVR/plugins/fHDHR_plugin_stream_vlc/__init__.py
2021-01-31 15:59:33 -05:00

218 lines
8.3 KiB
Python

import os
import sys
import subprocess
from fHDHR.exceptions import TunerError
def setup(plugin):
# Check config for vlc path
vlc_path = None
if plugin.config.dict["vlc"]["path"]:
# verify path is valid
if os.path.isfile(plugin.config.dict["vlc"]["path"]):
vlc_path = plugin.config.dict["vlc"]["path"]
else:
plugin.logger.warning("Failed to find vlc at %s." % plugin.config.dict["vlc"]["path"])
if not vlc_path:
plugin.logger.info("Attempting to find vlc in PATH.")
if plugin.config.internal["versions"]["Operating System"]["version"] in ["Linux", "Darwin"]:
find_vlc_command = ["which", "vlc"]
elif plugin.config.internal["versions"]["Operating System"]["version"] in ["Windows"]:
find_vlc_command = ["where", "vlc"]
vlc_proc = subprocess.Popen(find_vlc_command, stdout=subprocess.PIPE)
vlc_path = vlc_proc.stdout.read().decode().strip("\n")
vlc_proc.terminate()
vlc_proc.communicate()
vlc_proc.kill()
if not vlc_path:
vlc_path = None
elif vlc_path.isspace():
vlc_path = None
if vlc_path:
plugin.config.dict["vlc"]["path"] = vlc_path
if vlc_path:
vlc_command = [vlc_path, "--version", "pipe:stdout"]
try:
vlc_proc = subprocess.Popen(vlc_command, stdout=subprocess.PIPE)
vlc_version = vlc_proc.stdout.read().decode().split("version ")[1].split('\n')[0]
except FileNotFoundError:
vlc_version = None
except PermissionError:
vlc_version = None
finally:
vlc_proc.terminate()
vlc_proc.communicate()
vlc_proc.kill()
if not vlc_version:
vlc_version = "Missing"
plugin.logger.warning("Failed to find vlc.")
plugin.config.register_version("vlc", vlc_version, "env")
class Plugin_OBJ():
def __init__(self, fhdhr, plugin_utils, stream_args, tuner):
self.fhdhr = fhdhr
self.plugin_utils = plugin_utils
self.stream_args = stream_args
self.tuner = tuner
if self.plugin_utils.config.internal["versions"]["vlc"]["version"] == "Missing":
raise TunerError("806 - Tune Failed: VLC Missing")
self.bytes_per_read = int(self.plugin_utils.config.dict["streaming"]["bytes_per_read"])
self.vlc_command = self.vlc_command_assemble(stream_args)
def get(self):
vlc_proc = subprocess.Popen(self.vlc_command, stdout=subprocess.PIPE)
def generate():
try:
while self.tuner.tuner_lock.locked():
chunk = vlc_proc.stdout.read(self.bytes_per_read)
if not chunk:
break
# raise TunerError("807 - No Video Data")
yield chunk
chunk_size = int(sys.getsizeof(chunk))
self.tuner.add_downloaded_size(chunk_size)
self.plugin_utils.logger.info("Connection Closed: Tuner Lock Removed")
except GeneratorExit:
self.plugin_utils.logger.info("Connection Closed.")
except Exception as e:
self.plugin_utils.logger.info("Connection Closed: %s" % e)
finally:
vlc_proc.terminate()
vlc_proc.communicate()
vlc_proc.kill()
self.plugin_utils.logger.info("Connection Closed: Tuner Lock Removed")
if hasattr(self.fhdhr.origins.origins_dict[self.tuner.origin], "close_stream"):
self.fhdhr.origins.origins_dict[self.tuner.origin].close_stream(self.tuner.number, self.stream_args)
self.tuner.close()
# raise TunerError("806 - Tune Failed")
return generate()
def vlc_command_assemble(self, stream_args):
vlc_command = [
self.plugin_utils.config.dict["vlc"]["path"],
"-I", "dummy", stream_args["stream_info"]["url"],
]
# vlc_command.extend(self.vlc_headers(stream_args))
vlc_command.extend(self.vlc_duration(stream_args))
vlc_command.extend(self.vlc_loglevel())
vlc_command.extend(["--sout"])
vlc_command.extend(self.transcode_profiles(stream_args))
return vlc_command
def vlc_headers(self, stream_args):
vlc_command = []
return vlc_command
def vlc_duration(self, stream_args):
vlc_command = []
if stream_args["duration"]:
vlc_command.extend(["--run-time=%s" % str(stream_args["duration"])])
return vlc_command
def vlc_loglevel(self):
vlc_command = []
log_level = self.plugin_utils.config.dict["logging"]["level"].lower()
loglevel_dict = {
"debug": "3",
"info": "0",
"error": "1",
"warning": "2",
"critical": "1",
}
vlc_command.extend(["--log-verbose=", loglevel_dict[log_level]])
if log_level not in ["info", "debug"]:
vlc_command.extend(["--quiet"])
return vlc_command
def transcode_profiles(self, stream_args):
# TODO implement actual profiles here
vlc_command = []
if stream_args["transcode_quality"]:
self.plugin_utils.logger.info("Client requested a %s transcode for stream." % stream_args["transcode_quality"])
transcode_dict = {}
if not stream_args["transcode_quality"] or stream_args["transcode_quality"] == "heavy":
# dummy do nothing line
vlc_command.extend([])
elif stream_args["transcode_quality"] == "mobile":
transcode_dict["transcode"] = {
"width": "1280",
"height": "720",
"vb": "500",
"ab": "128"
}
elif stream_args["transcode_quality"] == "internet720":
transcode_dict["transcode"] = {
"width": "1280",
"height": "720",
"vb": "1000",
"ab": "196"
}
elif stream_args["transcode_quality"] == "internet480":
transcode_dict["transcode"] = {
"width": "848",
"height": "480",
"vb": "400",
"ab": "128"
}
elif stream_args["transcode_quality"] == "internet360":
transcode_dict["transcode"] = {
"width": "640",
"height": "360",
"vb": "250",
"ab": "96"
}
elif stream_args["transcode_quality"] == "internet240":
transcode_dict["transcode"] = {
"width": "432",
"height": "240",
"vb": "250",
"ab": "96"
}
transcode_dict["std"] = {
"mux": "ts",
"access": "file",
"dst": "-"
}
topkey_index = 0
vlc_transcode_string = ""
for topkey in list(transcode_dict.keys()):
if not topkey_index:
topkey_index += 1
vlc_transcode_string += "#"
else:
vlc_transcode_string += ":"
vlc_transcode_string += "%s{" % topkey
vlc_transcode_string += ",".join(["%s=%s" % (x, transcode_dict[topkey][x]) for x in list(transcode_dict[topkey].keys())])
vlc_transcode_string += "}"
vlc_command.extend([vlc_transcode_string])
return vlc_command