From: Guillaume Pellerin Date: Mon, 9 Jun 2025 07:35:22 +0000 (+0200) Subject: globalize params simplifing engine switch, cleanup X-Git-Tag: 4.2.0~4 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=bf6d56dd0b43aa4e18857619e19a59da19d082ae;p=telecaster-server.git globalize params simplifing engine switch, cleanup --- diff --git a/bin/streaming/telecaster.py b/bin/streaming/telecaster.py index 8db0ce9..ad1f15b 100755 --- a/bin/streaming/telecaster.py +++ b/bin/streaming/telecaster.py @@ -10,14 +10,14 @@ from threading import Thread from copy import deepcopy -VIDEO_PIPELINE_BASE="""{video_source} {video_options} \ +VIDEO_PIPELINE_BASE="""{gst_video_source} {gst_video_options} \ ! {format}, width={width}, height={height}, framerate={framerate}/1 \ ! {decoder} \ ! queue ! videoflip method={flip} \ ! queue ! videoconvert \ ! queue ! vp8enc threads=4 deadline=2 target-bitrate={vp8_bitrate} \ ! muxout. \ - {audio_source} {audio_options} client-name="webm_streaming_{id}_audio" ! audio/x-raw, format=F32LE, channels={channels} \ + {gst_audio_source} {gst_audio_options} client-name="webm_streaming_{id}_audio" ! audio/x-raw, format=F32LE, channels={channels} \ ! queue ! audiocheblimit mode=high-pass cutoff={hp_frequency} poles={hp_poles} \ ! queue ! volume volume={volume_pre} \ ! queue ! audiodynamic characteristics=soft-knee mode=compressor threshold={comp_threshold} ratio={comp_ratio} \ @@ -30,7 +30,7 @@ VIDEO_PIPELINE_BASE="""{video_source} {video_options} \ ! queue ! shout2send ip={ip} port={port} password={password} mount=telecaster_live_{id}.webm > /dev/null """ -AUDIO_PIPELINE_BASE="""{audio_source} {audio_options} client-name="mp3_streaming_audio" \ +AUDIO_PIPELINE_BASE="""{gst_audio_source} {gst_audio_options} client-name="mp3_streaming_audio" \ ! audio/x-raw, format=F32LE, channels={channels} \ ! queue ! audiocheblimit mode=high-pass cutoff={hp_frequency} poles={hp_poles} \ ! queue ! volume volume={volume_pre} \ @@ -46,26 +46,33 @@ BOOT_TIME_DELAY = 1 DEFAULT_CONFIG_FILE = "/etc/telecaster/telecaster.yml" -JACK_CONFIG = {"engine": "jackd", - "options": "-R -P{priority} -dalsa -r{samplerate} -p{buffer} -n3 -Chw:{card} -Phw:{card}", - "tools": ["qjackctl", "catia", "konsole"], - "gst_audio_source": "jackaudiosrc", - "gst_audio_options": "connect=2 low-latency=true", - "connect": - ["jack_connect system:capture_1 webm_streaming_0_audio:in_jackaudiosrc0_1", - "jack_connect system:capture_2 webm_streaming_0_audio:in_jackaudiosrc0_2", - "jack_connect system:capture_1 mp3_streaming_audio:in_jackaudiosrc0_1", - "jack_connect system:capture_2 mp3_streaming_audio:in_jackaudiosrc0_2" - ] - } - -PIPEWIRE_CONFIG = {"engine": "pipewire", - "options": "", - "gst_audio_source": "pipewiresrc", - "gst_audio_options": "target-object={target_object}", - "tools": ["qpwgraph", "konsole"], - "connect":"" - } +PARAMS = { + "jack": { + "engine": "jackd", + "options": "-R -P{priority} -dalsa -r{samplerate} -p{buffer} -n3 -Chw:{card} -Phw:{card}", + "tools": ["qjackctl", "catia", "konsole"], + "gst_video_source": "v4l2src", + "gst_video_options": "device=/dev/video{id}", + "gst_audio_source": "jackaudiosrc", + "gst_audio_options": "connect=2 low-latency=true", + "connect": + ["jack_connect system:capture_1 webm_streaming_0_audio:in_jackaudiosrc0_1", + "jack_connect system:capture_2 webm_streaming_0_audio:in_jackaudiosrc0_2", + "jack_connect system:capture_1 mp3_streaming_audio:in_jackaudiosrc0_1", + "jack_connect system:capture_2 mp3_streaming_audio:in_jackaudiosrc0_2" + ] +}, + "pipewire": { + "engine": "pipewire", + "options": "", + "gst_video_source": "pipewiresrc", + "gst_video_options": "target-object=v4l2:/dev/video{id}", + "gst_audio_source": "pipewiresrc", + "gst_audio_options": "target-object={target_object}", + "tools": ["qpwgraph", "konsole"], + "connect":"" + } +} class TeleCasterGStream(Thread): @@ -73,7 +80,6 @@ class TeleCasterGStream(Thread): def __init__(self, pipeline): Thread.__init__(self) self.pipeline = pipeline - # print(self.pipeline) def run(self): os.system('gst-launch-1.0 ' + self.pipeline + ' & ') @@ -110,19 +116,26 @@ class TeleCasterCommand: class TeleCaster(Thread): - def __init__(self, conf_file_path): + def __init__(self, conf_file_path, verbose, dry_run): Thread.__init__(self) conf_file = open(conf_file_path, 'r') + self.verbose = verbose + self.dry_run = dry_run self.conf = yaml.safe_load(conf_file)["telecaster"] self.stream_types = ["audio", "video"] self.deefuzzer_video_conf_file = "/tmp/telecaster_deefuzzer_webm_monitor.yml" self.deefuzzer_audio_conf_file = "/tmp/telecaster_deefuzzer_mp3_monitor.yml" # print(self.conf) - audio_source = self.conf["audio"]["gstreamer"]["audio_source"] - if "pipewire" in audio_source: - self.audio_config = PIPEWIRE_CONFIG - elif "jack" in audio_source: - self.audio_config = JACK_CONFIG + + audio_engine = self.conf["audio"]["engine"] + + self.params = PARAMS[audio_engine] + self.params["options"] = self.params["options"].format(**self.conf["audio"][audio_engine]) + self.params["gst_audio_options"] = self.params["gst_audio_options"].format(**self.conf["audio"][audio_engine]) + + if self.verbose: + print(self.params) + def write_conf(self, conf_dict, path): filename, ext = os.path.splitext(path) @@ -136,25 +149,34 @@ class TeleCaster(Thread): for param in params: command = "v4l2-ctl -d %s -c %s=%s" % (video["id"], param, params[param]) args = shlex.split(command) - # print(args) - subprocess.call(command, shell=True) + if self.verbose: + print(command) + if not self.dry_run: + subprocess.call(command, shell=True) def audio_engine_start(self): - command = self.audio_config["engine"] + " " + self.audio_config["options"].format(**self.conf["audio"]["jack"]) + command = self.params["engine"] + " " + self.params["options"] thread = TeleCasterThreadedCommand(command) - thread.start() + if self.verbose: + print(command) + if not self.dry_run: + thread.start() time.sleep(BOOT_TIME_DELAY) def audio_tools_start(self): - for tool in self.audio_config["tools"]: + for tool in self.params["tools"]: command = TeleCasterCommand(tool) - command.start() + if self.verbose: + print(tool) + if not self.dry_run: + command.start() def deefuzzer_start(self, conf, conf_file): # print(self.conf) self.write_conf(conf, conf_file) deefuzzer = TeleCasterDeeFuzzer(conf_file) - deefuzzer.start() + if not self.dry_run: + deefuzzer.start() def video_start(self): deefuzzer_default_conf = deepcopy(self.conf["video"]["deefuzzer"]) @@ -169,11 +191,18 @@ class TeleCaster(Thread): if "v4l2-ctl" in video: self.v4l2_ctl(video) + self.params["gst_video_options"] = self.params["gst_video_options"].format(**video) + pipeline = VIDEO_PIPELINE_BASE.format(**video, **self.conf["audio"]["gstreamer"], - **self.conf["server"]) + **self.conf["server"], + **self.params, + ) stream = TeleCasterGStream(pipeline) - stream.start() + if self.verbose: + print(pipeline) + if not self.dry_run: + stream.start() time.sleep(BOOT_TIME_DELAY) deefuzzer_local_conf = deepcopy(deefuzzer_station_conf) @@ -194,7 +223,8 @@ class TeleCaster(Thread): deefuzzer_global_conf["deefuzzer"]["station"].append(deefuzzer_local_conf) time.sleep(BOOT_TIME_DELAY) - self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_video_conf_file) + if not self.dry_run: + self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_video_conf_file) def audio_start(self): deefuzzer_default_conf = deepcopy(self.conf["audio"]["deefuzzer"]) @@ -205,9 +235,14 @@ class TeleCaster(Thread): pipeline = AUDIO_PIPELINE_BASE.format( **self.conf["audio"]["gstreamer"], - **self.conf["server"]) + **self.conf["server"], + **self.params, + ) stream = TeleCasterGStream(pipeline) - stream.start() + if self.verbose: + print(pipeline) + if not self.dry_run: + stream.start() time.sleep(BOOT_TIME_DELAY) deefuzzer_local_conf = deepcopy(deefuzzer_station_conf) @@ -218,12 +253,16 @@ class TeleCaster(Thread): deefuzzer_global_conf["deefuzzer"]["station"].append(deefuzzer_local_conf) time.sleep(BOOT_TIME_DELAY) - self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_audio_conf_file) + if not self.dry_run: + self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_audio_conf_file) def connect(self): - for post_command in self.audio_config["connect"]: - command = TeleCasterCommand(post_command) - command.start() + for connect in self.params["connect"]: + command = TeleCasterCommand(connect) + if self.verbose: + print(connect) + if not self.dry_run: + command.start() def run(self): self.audio_engine_start() @@ -233,13 +272,15 @@ class TeleCaster(Thread): self.connect() - def main(): + verbose = False + dry_run = False + if len(sys.argv) >= 2: - tc = TeleCaster(sys.argv[-1]) + tc = TeleCaster(sys.argv[-1], verbose, dry_run) tc.start() elif os.path.exists(DEFAULT_CONFIG_FILE): - tc = TeleCaster(DEFAULT_CONFIG_FILE) + tc = TeleCaster(DEFAULT_CONFIG_FILE, verbose, dry_run) tc.start() else: sys.exit() diff --git a/etc/telecaster/telecaster.yml b/etc/telecaster/telecaster.yml index c176b5a..2f2b045 100644 --- a/etc/telecaster/telecaster.yml +++ b/etc/telecaster/telecaster.yml @@ -9,10 +9,6 @@ telecaster: gstreamer: - id: 0 name: logitech - video_source: v4l2src - video_options: device=/dev/video0 - #video_source: pipewiresrc - #video_options: target-object=v4l2:/dev/video0 width: 1280 height: 720 framerate: 30 @@ -86,13 +82,8 @@ telecaster: samplerate: 48000 pipewire: target_object: telecaster_source - # target_object=alsa:acp:ArturiaMsd:0:capture + #target_object=alsa:acp:ArturiaMsd:0:capture gstreamer: - audio_source: jackaudiosrc - audio_options: connect=2 - #audio_source: pipewiresrc - #audio_options: target-object=telecaster_source - #audio_options: target-object=alsa:acp:ArturiaMsd:0:capture channels: 2 opus_bitrate: 96000 mp3_quality: 4.0