From 630907ab5007c60bdd07d9dc44c5d19a7495090f Mon Sep 17 00:00:00 2001 From: Guillaume Pellerin Date: Tue, 6 Feb 2024 16:01:18 +0100 Subject: [PATCH] - convert telecaster conf to yml - add global telecaster manager handling multiple video sources - embed deefuzzer confs into telecaster one --- bin/streaming/telecaster.py | 183 ++++++++++++++++++ bin/streaming/telecaster_start.sh | 60 ++++++ .../deefuzzer/telecaster_monitor.yml | 92 +++++++++ .../deefuzzer/telecaster_mp3_monitor.yml | 66 ++++--- .../deefuzzer/telecaster_webm_monitor.yml | 57 ++++-- etc/telecaster/telecaster.yml | 139 +++++++++++++ 6 files changed, 562 insertions(+), 35 deletions(-) create mode 100755 bin/streaming/telecaster.py create mode 100644 bin/streaming/telecaster_start.sh create mode 100644 etc/telecaster/deefuzzer/telecaster_monitor.yml create mode 100644 etc/telecaster/telecaster.yml diff --git a/bin/streaming/telecaster.py b/bin/streaming/telecaster.py new file mode 100755 index 0000000..c2479e7 --- /dev/null +++ b/bin/streaming/telecaster.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python + +import os +import shlex +import subprocess +import sys +import yaml +from threading import Thread +from copy import deepcopy + + +VIDEO_PIPELINE_BASE="""v4l2src device=/dev/video{id} ! {format}, width={width}, height={height}, framerate={framerate}/1 \ + ! queue ! {decoder} \ + ! queue ! videoflip method={flip} \ + ! queue ! videoconvert \ + ! queue ! vp8enc threads=4 deadline=2 \ + ! queue ! muxout. \ + jackaudiosrc connect=2 ! audio/x-raw, format=F32LE, channels={channels} \ + ! queue ! audiocheblimit mode=high-pass cutoff=120 poles=4 \ + ! queue ! volume volume={gain_pre} \ + ! queue ! audiodynamic characteristics=soft-knee mode=compressor threshold=0.125 ratio=0.125 \ + ! queue ! volume volume={gain_post} \ + ! queue ! audiodynamic characteristics=hard-knee mode=compressor threshold=0.95 ratio=0.001 \ + ! queue ! audioconvert \ + ! queue ! opusenc bitrate={opus_bitrate} \ + ! queue ! muxout. \ + webmmux streamable=true name=muxout \ + ! queue ! shout2send ip={ip} port={port} password={password} mount=telecaster_live_{id}.webm +""" + +AUDIO_PIPELINE_BASE="""jackaudiosrc connect=2 ! audio/x-raw, format=F32LE, channels={channels} \ + ! queue ! audiocheblimit mode=high-pass cutoff=120 poles=4 \ + ! queue ! volume volume={gain_pre} \ + ! queue ! audiodynamic characteristics=soft-knee mode=compressor threshold=0.125 ratio=0.125 \ + ! queue ! volume volume={gain_post} \ + ! queue ! audiodynamic characteristics=hard-knee mode=compressor threshold=0.95 ratio=0.001 \ + ! queue ! audioconvert \ + ! queue ! lamemp3enc quality={mp3_quality} \ + ! queue ! shout2send ip={ip} port={port} password={password} mount=telecaster_live.mp3 +""" + +V4L2_LOGITECH_PARAMS = { + "power_line_frequency": 1, + "zoom_absolute": 128, + "focus_auto": 0, + "focus_absolute": 1, + "sharpness": 128 +} + + +class TeleCasterGStream(Thread): + + def __init__(self, pipeline): + Thread.__init__(self) + self.pipeline = pipeline + + def run(self): + os.system('gst-launch-1.0 ' + self.pipeline + ' & ') + + +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 + ' & ') + + +class TeleCasterDeeFuzzer(Thread): + + def __init__(self, conf_file): + Thread.__init__(self) + self.conf_file = conf_file + + def run(self): + os.system('deefuzzer ' + self.conf_file + ' & ') + + +class TeleCaster(Thread): + + def __init__(self, conf_file_path): + Thread.__init__(self) + conf_file = open(conf_file_path, 'r') + self.conf = yaml.safe_load(conf_file)["telecaster"] + self.stream_types = ["audio, ""video"] + self.deefuzzer_video_conf_file = "/tmp/telecaster_deefuzzer_video_monitor.yml" + self.deefuzzer_audio_conf_file = "/tmp/telecaster_deefuzzer_audio_monitor.yml" + # print(self.conf) + + def write_conf(self, conf_dict, path): + filename, ext = os.path.splitext(path) + f = open(path, 'w') + yaml.dump(conf_dict, f) + f.close() + + def logitech_c92x_setup(self, video): + params = V4L2_LOGITECH_PARAMS + params["zoom_absolute"] = video["zoom"] + params["sharpness"] = video["sharpness"] + + 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) + + def deefuzzer_start(self, conf, conf_file): + # print(self.conf) + self.write_conf(conf, conf_file) + deefuzzer = TeleCasterDeeFuzzer(conf_file) + deefuzzer.start() + + def video_start(self): + deefuzzer_default_conf = deepcopy(self.conf["video"]["deefuzzer"]) + deefuzzer_station_conf = deepcopy(deefuzzer_default_conf["station"]) + + deefuzzer_global_conf = {"deefuzzer": deepcopy(deefuzzer_default_conf)} + deefuzzer_global_conf["deefuzzer"]["station"] = [] +# + + for video in self.conf["video"]["gstreamer"]: + if "logitech" in video: + self.logitech_c92x_setup(video) + + pipeline = VIDEO_PIPELINE_BASE.format(**video, + **self.conf["audio"]["gstreamer"], + **self.conf["server"]) + stream = TeleCasterGStream(pipeline) + stream.start() + + deefuzzer_local_conf = deepcopy(deefuzzer_station_conf) + relay_url = "http://{ip}:{port}/telecaster_live_{id}.webm".format(**video, **self.conf["server"]) + deefuzzer_local_conf["relay"]["url"] = relay_url + deefuzzer_local_conf["record"]["dir"] = self.conf["record_dir"] + os.sep + "webm" + os.sep + str(video["id"]) + deefuzzer_local_conf["server"]["mountpoint"] = "monitor_" + str(video["id"]) + ".webm" + print(deefuzzer_local_conf) + deefuzzer_global_conf["deefuzzer"]["station"].append(deefuzzer_local_conf) + + self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_video_conf_file) + + def audio_start(self): + deefuzzer_default_conf = deepcopy(self.conf["audio"]["deefuzzer"]) + deefuzzer_station_conf = deepcopy(deefuzzer_default_conf["station"]) + + deefuzzer_global_conf = {"deefuzzer": deepcopy(deefuzzer_default_conf)} + deefuzzer_global_conf["deefuzzer"]["station"] = [] + + + pipeline = AUDIO_PIPELINE_BASE.format( + **self.conf["audio"]["gstreamer"], + **self.conf["server"]) + stream = TeleCasterGStream(pipeline) + stream.start() + + + deefuzzer_local_conf = deepcopy(deefuzzer_station_conf) + # print(deefuzzer_local_conf) + relay_url = "http://{ip}:{port}/telecaster_live.mp3".format(**self.conf["server"]) + deefuzzer_local_conf["relay"]["url"] = relay_url + deefuzzer_local_conf["record"]["dir"] = self.conf["record_dir"] + os.sep + "mp3" + deefuzzer_global_conf["deefuzzer"]["station"].append(deefuzzer_local_conf) + + self.deefuzzer_start(deefuzzer_global_conf, self.deefuzzer_audio_conf_file) + + def run(self): + self.video_start() + self.audio_start() + + +def main(): + if len(sys.argv) >= 2: + tc = TeleCaster(sys.argv[-1]) + tc.start() + else: + sys.exit() + + +if __name__ == '__main__': + main() + diff --git a/bin/streaming/telecaster_start.sh b/bin/streaming/telecaster_start.sh new file mode 100644 index 0000000..37259a7 --- /dev/null +++ b/bin/streaming/telecaster_start.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +set -e + +source /etc/telecaster/telecaster.conf + +TELECASTER_PATH=/srv/telecaster/telecaster-server/ + +# jackd + +jackd $JACK_OPTIONS & + +sleep 2 + +# telecaster + +konsole & + +qjackctl & + +sleep 1 + +$TELECASTER_PATH/bin/streaming/tc_audio_mp3_icecast-gst1.sh & + +sleep 1 + +$TELECASTER_PATH/bin/streaming/tc_video_simple_webm_stream-gst1-double.sh & + +sleep 3 + +# JACK ports setup + +# STEREO setup +# 1: L +# 2: R + +#jack_disconnect system:capture_1 gst-launch-1.0:in_jackaudiosrc0_1 +#jack_disconnect system:capture_2 gst-launch-1.0:in_jackaudiosrc0_2 + +#jack_disconnect system:capture_1 gst-launch-1.0-01:in_jackaudiosrc0_1 +#jack_disconnect system:capture_2 gst-launch-1.0-01:in_jackaudiosrc0_2 + +#jack_connect system:capture_1 gst-launch-1.0:in_jackaudiosrc0_1 +#jack_connect system:capture_2 gst-launch-1.0:in_jackaudiosrc0_2 + +# ADDITIONAL mics +# 3: C + +# jack_connect system:capture_3 gst-launch-1.0:in_jackaudiosrc0_1 +# jack_connect system:capture_3 gst-launch-1.0:in_jackaudiosrc0_2 + +# jack_connect system:capture_3 gst-launch-1.0-01:in_jackaudiosrc0_1 +# jack_connect system:capture_3 gst-launch-1.0-01:in_jackaudiosrc0_2 + +#Audio monitor +deefuzzer $TELECASTER_PATH/etc/telecaster/deefuzzer/telecaster_mp3_monitor.yaml & + +#Video monitor +deefuzzer $TELECASTER_PATH/etc/telecaster/deefuzzer/telecaster_webm_monitor_double.yaml & + diff --git a/etc/telecaster/deefuzzer/telecaster_monitor.yml b/etc/telecaster/deefuzzer/telecaster_monitor.yml new file mode 100644 index 0000000..07f5600 --- /dev/null +++ b/etc/telecaster/deefuzzer/telecaster_monitor.yml @@ -0,0 +1,92 @@ +deefuzzer: + log: /var/log/telecaster/telecaster_monitor.log + m3u: /var/www/m3u/telecaster_monitor.m3u + station: + - control: + mode: 1 + port: 16002 + infos: + description: TeleCaster WebM monitor stream + genre: Vocal + name: monitor_1.webm + short_name: monitor_1.webm + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: '0' + shuffle: '0' + media: + bitrate: '512' + dir: /usr/local/share/telecaster/media/webm + format: webm + ogg_quality: '4' + samplerate: '48000' + shuffle: '0' + voices: '1' + record: + dir: /home/telecaster/trash/webm/1 + mode: 1 + relay: + author: TeleCaster + mode: '1' + url: http://127.0.0.1:8000/telecaster_live_1.webm + rss: + dir: /var/www/rss + enclosure: '0' + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor_1.webm + port: '8000' + public: '0' + sourcepassword: source2parisson + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: '0' + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla + - control: + mode: 1 + port: 16001 + infos: + description: TeleCaster MP3 monitor + genre: Vocal + name: monitor.mp3 + short_name: monitor.mp3 + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: 0 + shuffle: 1 + media: + bitrate: 96 + dir: /usr/local/share/telecaster/media/mp3 + format: mp3 + ogg_quality: 4 + samplerate: 48000 + shuffle: 0 + voices: '2' + record: + dir: /home/telecaster/trash/mp3 + mode: 1 + relay: + author: Inconnu + mode: 1 + url: http://127.0.0.1:8000/telecaster_live.mp3 + rss: + dir: /var/www/rss + enclosure: 0 + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor.mp3 + port: 8000 + public: 0 + sourcepassword: source2parisson + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: 0 + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla diff --git a/etc/telecaster/deefuzzer/telecaster_mp3_monitor.yml b/etc/telecaster/deefuzzer/telecaster_mp3_monitor.yml index bd8f376..4ba8b96 100644 --- a/etc/telecaster/deefuzzer/telecaster_mp3_monitor.yml +++ b/etc/telecaster/deefuzzer/telecaster_mp3_monitor.yml @@ -2,25 +2,47 @@ deefuzzer: log: /var/log/telecaster/telecaster_mp3_monitor.log m3u: /var/www/m3u/telecaster_mp3_monitor.m3u station: - control: {mode: 1, port: 16001} - infos: {description: TeleCaster MP3 monitor, - genre: Vocal, - name: monitor.mp3, - short_name: monitor.mp3, - url: 'https://www.parisson.com'} - jingles: {dir: /path/to/jingles, mode: 0, shuffle: 1} - media: {bitrate: 96, - dir: /usr/local/share/telecaster/media/mp3, - format: mp3, ogg_quality: 4, - samplerate: 48000, shuffle: 0, voices: '2'} - record: {dir: /home/telecaster/trash/mp3, mode: 1} - relay: {author: Inconnu, mode: 1, - url: 'http://127.0.0.1:8000/telecaster_live.mp3'} - rss: {dir: /var/www/rss, enclosure: 0, - media_url: 'http://localhost/rss/'} - server: {host: 127.0.0.1, mountpoint: monitor.mp3, - port: 8000, public: 0, - sourcepassword: source2parisson, type: icecast} - twitter: {key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE, - mode: 0, secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4, - tags: bla bla} + control: + mode: 1 + port: 16001 + infos: + description: TeleCaster MP3 monitor + genre: Vocal + name: monitor.mp3 + short_name: monitor.mp3 + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: 0 + shuffle: 1 + media: + bitrate: 96 + dir: /usr/local/share/telecaster/media/mp3 + format: mp3 + ogg_quality: 4 + samplerate: 48000 + shuffle: 0 + voices: '2' + record: + dir: /home/telecaster/trash/mp3 + mode: 1 + relay: + author: Inconnu + mode: 1 + url: http://127.0.0.1:8000/telecaster_live.mp3 + rss: + dir: /var/www/rss + enclosure: 0 + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor.mp3 + port: 8000 + public: 0 + sourcepassword: source2parisson + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: 0 + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla diff --git a/etc/telecaster/deefuzzer/telecaster_webm_monitor.yml b/etc/telecaster/deefuzzer/telecaster_webm_monitor.yml index 8ce7c84..c2c05b0 100644 --- a/etc/telecaster/deefuzzer/telecaster_webm_monitor.yml +++ b/etc/telecaster/deefuzzer/telecaster_webm_monitor.yml @@ -2,16 +2,47 @@ deefuzzer: log: /var/log/telecaster/telecaster_webm_monitor.log m3u: /var/www/m3u/telecaster_webm_monitor.m3u station: - control: {mode: 1, port: 16002} - infos: {description: TeleCaster WebM monitor stream, genre: Vocal, name: monitor_1.webm, short_name: monitor_1.webm, - url: 'https://www.parisson.com'} - jingles: {dir: /path/to/jingles, mode: '0', shuffle: '0'} - media: {bitrate: '512', dir: /usr/local/share/telecaster/media/webm, format: webm, ogg_quality: '4', - samplerate: '48000', shuffle: '0', voices: '1'} - record: {dir: /home/telecaster/trash/webm/1, mode: 1} - relay: {author: TeleCaster, mode: '1', url: 'http://127.0.0.1:8000/telecaster_live_1.webm'} - rss: {dir: /var/www/rss, enclosure: '0', media_url: 'http://localhost/rss/'} - server: {host: 127.0.0.1, port: '8000', public: '0', sourcepassword: source2parisson, - type: icecast, mountpoint: monitor_1.webm} - twitter: {key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE, mode: '0', secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4, - tags: bla bla} + control: + mode: 1 + port: 16002 + infos: + description: TeleCaster WebM monitor stream + genre: Vocal + name: monitor_1.webm + short_name: monitor_1.webm + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: '0' + shuffle: '0' + media: + bitrate: '512' + dir: /usr/local/share/telecaster/media/webm + format: webm + ogg_quality: '4' + samplerate: '48000' + shuffle: '0' + voices: '1' + record: + dir: /home/telecaster/trash/webm/1 + mode: 1 + relay: + author: TeleCaster + mode: '1' + url: http://127.0.0.1:8000/telecaster_live_1.webm + rss: + dir: /var/www/rss + enclosure: '0' + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor_1.webm + port: '8000' + public: '0' + sourcepassword: source2parisson + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: '0' + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla diff --git a/etc/telecaster/telecaster.yml b/etc/telecaster/telecaster.yml new file mode 100644 index 0000000..0409d12 --- /dev/null +++ b/etc/telecaster/telecaster.yml @@ -0,0 +1,139 @@ +telecaster: + server: + ip: 127.0.0.1 + port: 8000 + password: hackme + type: icecast + record_dir: /home/telecaster/monitor/ + video: + gstreamer: + - id: 0 + width: 848 + height: 480 + framerate: 30 + flip: rotate-180 + zoom: 140 + sharpness: 144 + format: image/jpeg + decoder: jpegdec + # logitech: true + - id: 4 + width: 864 + height: 480 + framerate: 30 + flip: rotate-180 + zoom: 140 + sharpness: 144 + format: image/jpeg + decoder: jpegdec + logitech: true + deefuzzer: + log: /var/log/telecaster/telecaster_webm_monitor.log + m3u: /tmp/telecaster_webm_monitor.m3u + station: + control: + mode: 0 + port: 16002 + infos: + description: TeleCaster WebM monitor stream + genre: Vocal + name: monitor_1.webm + short_name: monitor_1.webm + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: '0' + shuffle: '0' + media: + bitrate: '512' + dir: /home/telecaster/media/webm + format: webm + ogg_quality: '4' + samplerate: '48000' + shuffle: '0' + voices: '1' + record: + dir: /home/telecaster/trash/webm/1 + mode: 1 + relay: + author: TeleCaster + mode: '1' + url: http://127.0.0.1:8000/telecaster_live_0.webm + rss: + dir: /var/www/rss + enclosure: '0' + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor_0.webm + port: '8000' + public: '0' + sourcepassword: hackme + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: '0' + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla + + audio: + gstreamer: + channels: 2 + opus_bitrate: 96000 + mp3_quality: 4.0 + gain_pre: 2.5 + gain_post: 1.5 + jack: + driver: alsa + samplerate: 48000 + ring_buffers: 3 + phw: 3 + chw: 3 + deefuzzer: + log: /var/log/telecaster/telecaster_mp3_monitor.log + m3u: /tmp/telecaster_mp3_monitor.m3u + station: + control: + mode: 0 + port: 16001 + infos: + description: TeleCaster MP3 monitor + genre: Vocal + name: monitor.mp3 + short_name: monitor.mp3 + url: https://www.parisson.com + jingles: + dir: /path/to/jingles + mode: 0 + shuffle: 1 + media: + bitrate: 96 + dir: /home/telecaster/media/mp3 + format: mp3 + ogg_quality: 4 + samplerate: 48000 + shuffle: 0 + voices: '2' + record: + dir: /home/telecaster/trash/mp3 + mode: 1 + relay: + author: Inconnu + mode: 1 + url: http://127.0.0.1:8000/telecaster_live.mp3 + rss: + dir: /var/www/rss + enclosure: 0 + media_url: http://localhost/rss/ + server: + host: 127.0.0.1 + mountpoint: monitor.mp3 + port: 8000 + public: 0 + sourcepassword: hackme + type: icecast + twitter: + key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE + mode: 0 + secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4 + tags: bla bla -- 2.39.5