]> git.parisson.com Git - telecaster-server.git/commitdiff
globalize params simplifing engine switch, cleanup
authorGuillaume Pellerin <guillaume.pellerin@parisson.com>
Mon, 9 Jun 2025 07:35:22 +0000 (09:35 +0200)
committerGuillaume Pellerin <guillaume.pellerin@parisson.com>
Mon, 9 Jun 2025 07:36:02 +0000 (09:36 +0200)
bin/streaming/telecaster.py
etc/telecaster/telecaster.yml

index 8db0ce95e12fd08734d56720a0b067bb1797d7cd..ad1f15b0803287a6441d55c2b5f2e1de74efcc3b 100755 (executable)
@@ -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()
index c176b5a2806d3573af70684e898cefab4aa6ac89..2f2b045c3dac980c4bf3db9817f20b2c366645e2 100644 (file)
@@ -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