# Original Script by HeyyItsBran - bran.app. Refactored and modified by jaminmc.
import signal
import subprocess
import os
import obspython as obs
import platform
import shutil
def get_streamlink_path():
streamlink_executable = "streamlink" + platform.system().lower()
path_from_shutil = shutil.which(streamlink_executable)
if path_from_shutil is not None:
return path_from_shutil
# Fallback to common installation paths
common_paths = [
"/usr/local/bin/streamlink", # Common path on macOS and Linux
"/usr/bin/streamlink", # Another common path on Linux
"C:\\Program Files (x86)\\Streamlink\\bin\\streamlink.exe", # Common path on Windows
"/opt/homebrew/bin/streamlink", # Homebrew path on macOS
]
for path in common_paths:
if os.path.exists(path):
return path
return None
def script_description():
return '<h1>Streamlink source</h1><b>Connects Streamlink to a media source.</b><br /><br /><a href="https://streamlink.github.io/install.html">Get Streamlink</a>'
def script_properties():
props = obs.obs_properties_create()
obs.obs_properties_add_text(props, "url", "Stream URL", obs.OBS_TEXT_DEFAULT)
# Dropdown menu for quality settings
quality_prop = obs.obs_properties_add_list(
props,
"quality",
"Quality Settings",
obs.OBS_COMBO_TYPE_LIST,
obs.OBS_COMBO_FORMAT_STRING,
)
quality_values = ["best", "worst", "720p", "480p", "360p"]
for value in quality_values:
obs.obs_property_list_add_string(quality_prop, value, value)
obs.obs_properties_add_int(
props, "port", "Output Port (1024-65535)", 1024, 65535, 1
)
obs.obs_properties_add_text(
props, "args", "Custom arguments (optional)", obs.OBS_TEXT_DEFAULT
)
sourcesList = obs.obs_properties_add_list(
props,
"source",
"Media Source",
obs.OBS_COMBO_TYPE_EDITABLE,
obs.OBS_COMBO_FORMAT_STRING,
)
sources = obs.obs_enum_sources()
if sources is not None:
for source in sources:
source_id = obs.obs_source_get_unversioned_id(source)
if source_id == "ffmpeg_source":
name = obs.obs_source_get_name(source)
obs.obs_property_list_add_string(sourcesList, name, name)
obs.source_list_release(sources)
obs.obs_properties_add_button(props, "save", "Save and reload", save)
return props
def script_update(settings):
global source_name
source_name = obs.obs_data_get_string(settings, "source")
def script_defaults(settings):
obs.obs_data_set_default_string(settings, "url", "https://www.twitch.tv/leekbeats")
obs.obs_data_set_default_string(settings, "quality", "best")
obs.obs_data_set_default_int(settings, "port", 50495)
obs.obs_data_set_default_string(settings, "args", "--twitch-disable-ads")
def script_load(settings):
global daemon
global gblSettings
gblSettings = settings
streamlink_path = get_streamlink_path()
if streamlink_path is None:
print("[streamlink-source-cross.py] Streamlink executable not found.")
return
url = obs.obs_data_get_string(settings, "url")
quality = obs.obs_data_get_string(settings, "quality")
port = str(obs.obs_data_get_int(settings, "port"))
args = obs.obs_data_get_string(settings, "args")
# Construct the streamlink command
streamlink_cmd = [
streamlink_path,
url,
quality,
"--player-continuous-http",
"--player-external-http",
"--player-external-http-port",
port,
]
# Add custom arguments if provided
if args.strip():
streamlink_cmd.extend(args.split())
print("Executing Streamlink command:", streamlink_cmd)
try:
daemon = subprocess.Popen(
streamlink_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
print(
"[streamlink-source-cross.py] Streamlink process started in the background."
)
except Exception as e:
print("[streamlink-source-cross.py] Error starting Streamlink process:", str(e))
return
srcSettings = obs.obs_data_create()
obs.obs_data_set_bool(srcSettings, "is_local_file", False)
obs.obs_data_set_bool(srcSettings, "restart_on_activate", True)
obs.obs_data_set_int(srcSettings, "buffering_mb", 4)
obs.obs_data_set_string(srcSettings, "input", "http://127.0.0.1:" + port)
obs.obs_data_set_string(srcSettings, "input_format", "")
obs.obs_data_set_int(srcSettings, "reconnect_delay_sec", 10)
obs.obs_data_set_bool(srcSettings, "hw_decode", True)
obs.obs_data_set_bool(srcSettings, "clear_on_media_end", True)
obs.obs_data_set_bool(srcSettings, "close_when_inactive", False)
obs.obs_data_set_int(srcSettings, "color_range", 0)
obs.obs_data_set_bool(srcSettings, "linear_alpha", False)
obs.obs_data_set_bool(srcSettings, "seekable", False)
obs.obs_source_update(
obs.obs_get_source_by_name(obs.obs_data_get_string(settings, "source")),
srcSettings,
)
def script_unload():
os.kill(daemon.pid, signal.SIGKILL)
subprocess.Popen(["pkill", "streamlink" + platform.system().lower()])
def save(prop, btn):
script_unload()
script_load(gblSettings)