--- /dev/null
+#!/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()
+
--- /dev/null
+#!/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 &
+
--- /dev/null
+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
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
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
--- /dev/null
+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