diff options
| -rw-r--r-- | common-playbook.yml | 5 | ||||
| -rw-r--r-- | roles/bbb/tasks/main.yml | 10 | ||||
| -rwxr-xr-x | roles/bbb/templates/bigbluebutton.yml | 73 | ||||
| -rw-r--r-- | roles/bbb/templates/video.yml | 81 | ||||
| -rw-r--r-- | roles/caption/tasks/main.yml | 1 | ||||
| -rw-r--r-- | roles/lounge/defaults/main.yml | 4 | ||||
| -rw-r--r-- | roles/lounge/tasks/main.yml | 40 | ||||
| -rw-r--r-- | roles/lounge/templates/error.html | 37 | ||||
| -rw-r--r-- | roles/lounge/templates/nginx-site-config | 63 | ||||
| -rw-r--r-- | roles/lounge/templates/thelounge.service | 11 | ||||
| -rw-r--r-- | roles/media/tasks/main.yml | 10 | ||||
| -rw-r--r-- | roles/media/templates/nginx-site-config | 16 | ||||
| -rw-r--r-- | roles/obs/tasks/mpv.yml | 3 | ||||
| -rw-r--r-- | roles/obs/templates/mpv.conf | 8 | ||||
| -rw-r--r-- | roles/pad-proxy/templates/etherpad.nginx.conf | 3 | ||||
| -rw-r--r-- | roles/prerec/tasks/main.yml | 2 | ||||
| -rw-r--r-- | roles/prerec/templates/Makefile | 88 | ||||
| -rwxr-xr-x | roles/prerec/templates/reencode-in-screen.sh | 6 | ||||
| -rwxr-xr-x | roles/prerec/templates/talk | 3 | ||||
| -rwxr-xr-x | roles/prerec/templates/thumbnail.sh | 2 | ||||
| -rw-r--r-- | roles/publish/tasks/main.yml | 4 |
21 files changed, 460 insertions, 10 deletions
diff --git a/common-playbook.yml b/common-playbook.yml index 4b12e4d..9cb44a3 100644 --- a/common-playbook.yml +++ b/common-playbook.yml @@ -71,3 +71,8 @@ tags: live roles: - live +- name: Set up lounge + hosts: front + tags: lounge + roles: + - lounge diff --git a/roles/bbb/tasks/main.yml b/roles/bbb/tasks/main.yml index 1a4b115..017e939 100644 --- a/roles/bbb/tasks/main.yml +++ b/roles/bbb/tasks/main.yml @@ -16,3 +16,13 @@ with_file: - ../../base/files/keys/sachac - ../../base/files/keys/orga +- name: Set up video.yml + become: true + template: + src: video.yml + dest: /usr/local/bigbluebutton/core/scripts/video.yml +- name: Set up bigbluebutton.yml + become: true + template: + src: bigbluebutton.yml + dest: /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml diff --git a/roles/bbb/templates/bigbluebutton.yml b/roles/bbb/templates/bigbluebutton.yml new file mode 100755 index 0000000..beb8ce8 --- /dev/null +++ b/roles/bbb/templates/bigbluebutton.yml @@ -0,0 +1,73 @@ +bbb_version: '3.0.9' +raw_audio_src: /var/freeswitch/meetings +mediasoup_video_src: /var/mediasoup/recordings +mediasoup_screenshare_src: /var/mediasoup/screenshare +webrtc_recorder_video_src: /var/lib/bbb-webrtc-recorder/recordings +webrtc_recorder_screenshare_src: /var/lib/bbb-webrtc-recorder/screenshare +webrtc_recorder_audio_src: /var/lib/bbb-webrtc-recorder/audio +raw_deskshare_src: /var/bigbluebutton/deskshare +raw_presentation_src: /var/bigbluebutton +notes_endpoint: http://127.0.0.1:9002/p +# Specify the notes formats we archive +# txt, doc and odt are also supported +notes_formats: + - etherpad + - html + - pdf +redis_host: 127.0.0.1 +redis_port: 6379 +# Uncomment and set password if redis require it. +# redis_password: changeme + +# redis_workers_host: 127.0.0.1 +# redis_workers_port: 6379 + +# Set to true to insert recording process status into +# redis list with key "store_recording_status: true". +# This is useful if you want to track progress status +# and have another script process it. +store_recording_status: false +# Whether to anonymize the sender of chat messages in the processed +# recordings. The settings here are the defaults; they can be overridden +# by passing meta parameters on the meeting create call. +# meta param: meta_bbb-anonymize-chat (true/false) +anonymize_chat: false +# By default only names of viewers are anonymized - if you would also +# like to anonymize moderators, you can set this to true: +# meta param: meta_bbb-anonymize-chat-moderators (true/false) +anonymize_chat_moderators: false +# By default, recordings assume the Viewer viewpoint (with all locks) +# so when webcamsOnlyForModerator=true, only moderators webcams are included in recordings. +# Use this option to ignore locks and assume Moderator viewpoint instead. +show_moderator_viewpoint: false +# Sequence of recording steps. Keys are the current step, values +# are the next step(s). Examples: +# current_step: next_step +# "current_step-format": "next_step-format" +# current_step: +# - next_step +# - another_step-format +steps: + archive: "sanity" + sanity: "captions" + captions: + - "process:presentation" + - "process:video" + "process:presentation": "publish:presentation" + "process:video": "publish:video" +# For PRODUCTION +log_dir: /var/log/bigbluebutton +events_dir: /var/bigbluebutton/events +recording_dir: /var/bigbluebutton/recording +published_dir: /var/bigbluebutton/published +captions_dir: /var/bigbluebutton/captions +playback_host: bbb.emacsverse.org +playback_protocol: https + +# For DEVELOPMENT +# This allows us to run the scripts manually +#scripts_dir: /home/ubuntu/dev/bigbluebutton/record-and-playback/core/scripts +#log_dir: /home/ubuntu/temp/log +#recording_dir: /home/ubuntu/temp/recording +#published_dir: /home/ubuntu/temp/published +#playback_host: bbb.emacsverse.org diff --git a/roles/bbb/templates/video.yml b/roles/bbb/templates/video.yml new file mode 100644 index 0000000..461372b --- /dev/null +++ b/roles/bbb/templates/video.yml @@ -0,0 +1,81 @@ +publish_dir: /var/bigbluebutton/published/video +playback_dir: /usr/local/bigbluebutton/core/playback/video +# offset applied to audio in the output video file +# audio_offset = 1000 means that the audio will be delayed by 1000ms +audio_offset: 0 + +layout: + width: 1280 + height: 720 + framerate: 24 + areas: + - name: presentation + x: 0 + y: 0 + width: 960 + height: 720 + - name: webcam + x: 960 + y: 0 + width: 320 + height: 720 + - name: deskshare + x: 0 + y: 0 + width: 960 + height: 720 + pad: true +nopresentation_layout: + width: 1280 + height: 720 + framerate: 24 + areas: + - name: webcam + x: 0 + y: 0 + width: 1280 + height: 720 +nowebcam_layout: + width: 1280 + height: 720 + framerate: 24 + areas: + - name: presentation + x: 0 + y: 0 + width: 1280 + height: 720 + - name: deskshare + x: 0 + y: 0 + width: 1280 + height: 720 + pad: true +formats: + #- mimetype: 'video/mp4' + # extension: m4v + # parameters: + # - [ '-c:v', 'copy', # Use working format codec defined in core/lib/recordandplayback/edl/video.rb + # '-c:a', 'aac', '-b:a', '128K', + # '-f', 'mp4', '-movflags', 'faststart' ] + # postprocess: [] + - mimetype: 'video/webm;codecs="vp09.00.41.08,opus"' + extension: webm + parameters: + # # Default single-pass encode + # #- [ '-c:v', 'libvpx-vp9', '-level', '4.1', '-b:v', '1800K', '-minrate', '900K', '-maxrate', '2610K', + # # '-crf', '31', '-quality', 'good', '-speed', '2', '-tile-columns', '2', '-threads', '2', + # # '-force_key_frames', 'expr:gte(t,n_forced*10)', + # # '-c:a', 'libopus', '-b:a', '64K', + # # '-f', 'webm' ] + # Slower but better quality two-pass encode + - [ '-c:v', 'libvpx-vp9', '-level', '4.1', '-b:v', '1800K', '-minrate', '900K', '-maxrate', '2610K', + '-crf', '31', '-quality', 'good', '-pass', '1', '-speed', '4', '-tile-columns', '2', '-threads', '2', + '-force_key_frames', 'expr:gte(t,n_forced*10)', + '-an', + '-f', 'webm' ] + - [ '-c:v', 'libvpx-vp9', '-level', '4.1', '-b:v', '1800K', '-minrate', '900K', '-maxrate', '2610K', + '-crf', '31', '-quality', 'good', '-pass', '2', '-speed', '2', '-tile-columns', '2', '-threads', '2', + '-force_key_frames', 'expr:gte(t,n_forced*10)', + '-c:a', 'libopus', '-b:a', '64K', + '-f', 'webm' ] diff --git a/roles/caption/tasks/main.yml b/roles/caption/tasks/main.yml index 96b3198..dbc5454 100644 --- a/roles/caption/tasks/main.yml +++ b/roles/caption/tasks/main.yml @@ -22,6 +22,7 @@ - num2words - name: Set up aeneas include_tasks: aeneas.yml + when: "'aeneas' in ansible_run_tags" - name: Create group group: name: "{{ emacsconf_group }}" diff --git a/roles/lounge/defaults/main.yml b/roles/lounge/defaults/main.yml new file mode 100644 index 0000000..26fbaaa --- /dev/null +++ b/roles/lounge/defaults/main.yml @@ -0,0 +1,4 @@ +lounge_domain: chat.emacsconf.org +irc_network: irc.libera.chat +irc_port: 6697 +irc_channels: "#emacsconf, #emacsconf-gen, #emacsconf-dev, and #emacsconf-org" diff --git a/roles/lounge/tasks/main.yml b/roles/lounge/tasks/main.yml new file mode 100644 index 0000000..8c6593f --- /dev/null +++ b/roles/lounge/tasks/main.yml @@ -0,0 +1,40 @@ +- name: Create directory + file: + path: /var/www/{{ lounge_domain }} + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + state: directory +- name: Set up error page + template: + src: error.html + dest: /var/www/{{ lounge_domain }}/error.html + mode: 0755 + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Create main configuration if needed + template: + src: nginx-site-config + dest: /etc/nginx/sites-available/{{ lounge_domain }} +- name: Make sure main configuration is enabled + file: + src: /etc/nginx/sites-available/{{ lounge_domain }} + dest: /etc/nginx/sites-enabled/{{ lounge_domain }} + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + force: no + state: link +- name: Reload configuration + become: true + service: + name: nginx + state: reloaded +- name: Install systemd configuration + tags: system + become: true + template: + src: thelounge.service + dest: /etc/systemd/system/thelounge.service + owner: root + group: root + mode: 0755 + when: not use_initd diff --git a/roles/lounge/templates/error.html b/roles/lounge/templates/error.html new file mode 100644 index 0000000..5e2a093 --- /dev/null +++ b/roles/lounge/templates/error.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>{{lounge_domain}} currently unavailable</title> + <style> + body { padding: 20px; font-family: Arial, sans-serif } + </style> +</head> +<body> + <h1>Web-based chat is currently unavailable (code 502)</h1> + + <p>The web-based IRC interface will be available during <a href="https://{{emacsconf_domain}}/{{emacsconf_year}}">{{emacsconf_name}} {{emacsconf_year}}</a>. Please check back then. In the meantime, you can also connect to {{irc_network}}:{{irc_port}} with your favorite IRC client and join {{irc_channels}}. + + <p>This page will refresh when the site is back. You can also check <a href="https://status.emacsconf.org">status.emacsconf.org</a> for updates.</p> + + <noscript>Your browser doesn’t support javascript. Please try refreshing the page manually every few minutes.</noscript> + + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> + <script> + var retryCurrent = 30, retryMax = 60 * 5; + async function check() { + let result = await fetch(window.location.href, { method: HEAD }).then(resp => { + if (resp.status == 200) { + window.location.reload(true); + } else if (resp.status == 502) { + if (retryCurrent < retryMax) { + retryCurrent = Math.min(retryCurrent * 2, retryMax); + } + setTimeout(check, retryCurrent * 1000); + } + }); + } + setTimeout(check_response, retryCurrent * 1000); + </script> +</body> +</html> diff --git a/roles/lounge/templates/nginx-site-config b/roles/lounge/templates/nginx-site-config new file mode 100644 index 0000000..cc6aa4d --- /dev/null +++ b/roles/lounge/templates/nginx-site-config @@ -0,0 +1,63 @@ +upstream backend { + server 127.0.0.1:9000; +} + +proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=thelounge_cache:10m max_size=3g inactive=120m use_temp_path=off; + + +server { + listen 80; + listen [::]:80; + server_name chat.emacsconf.org; + + include snippets/well-known-acme-challenge.conf; + + location /js-licenses.html { root /var/www/{{lounge_domain}}; } + + location / { + return 302 https://$server_name$request_uri; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{lounge_domain}}; + + include /etc/nginx/tls/{{emacsconf_domain}}.conf; + + location /js-licenses.html { root /var/www/{{lounge_domain}}; } + error_page 502 /error.html; + location = /error.html { + root /var/www/{{lounge_domain}}; + } + location / { + proxy_pass http://backend; + proxy_http_version 1.1; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + + # by default nginx times out connections in one minute + proxy_read_timeout 1d; + } + +} + +#server { +# listen 443 ssl http2; +# listen [::]:443 ssl http2; +# server_name chat.emacsconf.org; +# +# include /etc/nginx/tls/emacsconf.org.conf; +# root /var/www/chat.emacsconf.org; +#} + +server { + listen 80; + listen [::]:80; + server_name chat.emacsconf.com chat.emacsconf.net; + + return 302 $scheme://{{lounge_domain}}$request_uri; +} diff --git a/roles/lounge/templates/thelounge.service b/roles/lounge/templates/thelounge.service new file mode 100644 index 0000000..abc4868 --- /dev/null +++ b/roles/lounge/templates/thelounge.service @@ -0,0 +1,11 @@ +[Unit] +Description=The Lounge IRC Client +After=network.target + +[Service] +ExecStart=/usr/bin/thelounge start +User=thelounge +WorkingDirectory=/var/lib/thelounge + +[Install] +WantedBy=multi-user.target diff --git a/roles/media/tasks/main.yml b/roles/media/tasks/main.yml index e9daaef..94f10a3 100644 --- a/roles/media/tasks/main.yml +++ b/roles/media/tasks/main.yml @@ -49,11 +49,21 @@ template: src: nginx-include dest: /etc/nginx/sites-available/{{ media_server_name }}-{{ emacsconf_year }}-include +- name: Create 404 page + template: + src: 404.html + dest: /var/www/{{ media_server_name }}/404.html + - name: Create main configuration if needed template: src: nginx-site-config dest: /etc/nginx/sites-available/{{ media_server_name }} force: no +- name: Make sure 404 line is in main config + lineinfile: + line: error_page 404 403 /404.html; + dest: /etc/nginx/sites-available/{{ media_server_name }} + insertafter: "listen 443 ssl http2;" - name: Make sure main configuration is enabled file: src: /etc/nginx/sites-available/{{ media_server_name }} diff --git a/roles/media/templates/nginx-site-config b/roles/media/templates/nginx-site-config index ba25cba..f6a83b1 100644 --- a/roles/media/templates/nginx-site-config +++ b/roles/media/templates/nginx-site-config @@ -1,7 +1,17 @@ server { - listen 80; - server_name {{ media_server_name }}; - root /var/www/{{ media_server_name }}; + listen 80; + server_name {{ media_server_name }}; + root /var/www/{{ media_server_name }}; + error_page 404 403 /404.html; + location / { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + add_header Pragma "no-cache"; + expires 0; + } + types { + text/plain org; + } + location ~* \.vtt$ { add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; diff --git a/roles/obs/tasks/mpv.yml b/roles/obs/tasks/mpv.yml index 4120f8c..c5806a8 100644 --- a/roles/obs/tasks/mpv.yml +++ b/roles/obs/tasks/mpv.yml @@ -7,7 +7,8 @@ repo: deb https://non-gnu.uvt.nl/debian {{ ansible_distribution_release }} uvt - name: Install mpv apt: - name: mpv + name: mpv=0.38.0+fruit.1 + allow_downgrade: true - name: Download MPVC git: repo: https://github.com/lwilletts/mpvc.git diff --git a/roles/obs/templates/mpv.conf b/roles/obs/templates/mpv.conf index b9efaae..7b708aa 100644 --- a/roles/obs/templates/mpv.conf +++ b/roles/obs/templates/mpv.conf @@ -27,6 +27,14 @@ sub-shadow-color=0/1 sub-shadow-offset=1.2 sub-ass-force-style=Kerning=yes sub-ass-line-spacing=0 +osd-level=3 +osd-bar-align-x=1 +osd-bar-align-y=1 +osd-bar-h=0.1 +osd-bar-w=0.1 +osd-align-x=right +osd-align-y=bottom +osd-scale=0.3 [full] video-zoom=0 diff --git a/roles/pad-proxy/templates/etherpad.nginx.conf b/roles/pad-proxy/templates/etherpad.nginx.conf index b657b98..2c285af 100644 --- a/roles/pad-proxy/templates/etherpad.nginx.conf +++ b/roles/pad-proxy/templates/etherpad.nginx.conf @@ -24,6 +24,9 @@ server { proxy_buffering off; proxy_pass http://etherpad_upstream; } + location /emacsconf/?$ { + return 301 /p/{{ emacsconf_year }}; + } location /p/ { rewrite ^/p/(.*) /$1 redirect; } diff --git a/roles/prerec/tasks/main.yml b/roles/prerec/tasks/main.yml index a0a3cac..98b7f13 100644 --- a/roles/prerec/tasks/main.yml +++ b/roles/prerec/tasks/main.yml @@ -1,9 +1,11 @@ - name: Ensure the directory exists + become: true file: path: "{{ emacsconf_caption_dir }}/{{ item }}" state: directory owner: "{{ emacsconf_user }}" group: "{{ emacsconf_group }}" + recurse: true loop: - scripts - cache diff --git a/roles/prerec/templates/Makefile b/roles/prerec/templates/Makefile index f58c5d6..778ae3e 100644 --- a/roles/prerec/templates/Makefile +++ b/roles/prerec/templates/Makefile @@ -2,21 +2,41 @@ # To recreate this file, use ansible-playbook -i inventory.yml prod-playbook.yml --tags prerec-make -VIDEO_EXTS = mp4 mkv webm mov mpv +.ONESHELL: +SHELL := /bin/bash +# --- Shell Function Definition --- +# This function checks a given file ($1) for an audio stream. +# It returns the string "audio" if found, or nothing if not found. +# This makes the conditional check cleaner. +define IS_AUDIO_PRESENT_SCRIPT + ffprobe -loglevel error -select_streams a:0 \ + -show_entries stream=codec_type \ + -of default=noprint_wrappers=1:nokey=1 "$1" +endef +IS_AUDIO_PRESENT = $(IS_AUDIO_PRESENT_SCRIPT) + +source_patterns = $(foreach ext,$(VIDEO_EXTS),$(1)--original.$(ext)) +ANSWER_EXTS = mp4 mkv mov mpv m4v source_patterns = $(foreach ext,$(VIDEO_EXTS),$(1)--original.$(ext)) +answer_patterns = $(foreach ext,$(ANSWER_EXTS),$(1)--answers.$(ext)) PRERECS_ORIGINAL := $(wildcard emacsconf-*--original.*) +ANSWERS_ORIGINAL := $(wildcard emacsconf-*--answers.*) +ANSWER_PREFIXES := $(shell for f in $(ANSWERS_ORIGINAL); do echo "$${f%--answers.*}"; done) PREFIXES := $(shell for f in $(PRERECS_ORIGINAL); do echo "$${f%--original.*}"; done) +ANSWERS_REENCODED := $(addsuffix --answers--reencoded.webm, $(ANSWER_PREFIXES)) PRERECS_REENCODED := $(addsuffix --reencoded.webm, $(PREFIXES)) PRERECS_OPUS := $(addsuffix --reencoded.opus, $(PREFIXES)) +PRERECS_MAIN_OPUS := $(addsuffix --main.opus, $(PREFIXES)) PRERECS_MAIN := $(addsuffix --main.webm, $(PREFIXES)) PRERECS_CAPTIONS := $(addsuffix --reencoded.vtt, $(PREFIXES)) PRERECS_FINAL := $(wildcard emacsconf-*--final.webm) +WAVEFORMS := $(addsuffix --backstage--waveform.png, $(PREFIXES)) LINODE_BBB_ID := 67329098 .PHONY: all -all: reencoded opus main +all: reencoded opus main main-opus waveforms.png reencoded: $(PRERECS_REENCODED) @@ -26,6 +46,17 @@ captions: $(PRERECS_CAPTIONS) main: $(PRERECS_MAIN) +main-opus: $(PRERECS_MAIN_OPUS) + +waveforms: $(WAVEFORMS) + +answers: $(ANSWERS_REENCODED) + +emacsconf-%--answers--reencoded.webm: SOURCES = $(call answer_patterns, emacsconf-$*) +emacsconf-%--answers--reencoded.webm: + $(eval SOURCE := $(lastword $(sort $(wildcard $(SOURCES))))) + @echo $(SOURCE) $@ + emacsconf-%--reencoded.webm: SOURCES = $(call source_patterns, emacsconf-$*) emacsconf-%--reencoded.webm: $(eval SOURCE := $(lastword $(sort $(wildcard $(SOURCES))))) @@ -38,7 +69,12 @@ emacsconf-%--reencoded.webm: reencode-in-screen.sh "$(SOURCE)" emacsconf-%--reencoded.opus: emacsconf-%--reencoded.webm - ffmpeg -y -i "$<" -c:a copy "$@" + AUDIO_CHECK=$$( $(call IS_AUDIO_PRESENT, "$<") ) + if [ ! -z "$$AUDIO_CHECK" ]; then + ffmpeg -y -i "$<" -c:a copy "$@" + else + ffmpeg -y -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=48000 -t 1 -c:a libopus "$@" + fi emacsconf-%--answers.opus: emacsconf-%--answers.webm ffmpeg -y -i "$<" -c:a copy "$@" @@ -60,11 +96,20 @@ emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--normalized.opus emacsconf-%--main.webm: emacsconf-%--reencoded.webm cp "$<" "$@" +emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--main.vtt + cp "$<" "$@" + ffmpeg -i emacsconf-$*--reencoded.webm -i emacsconf-$*--main.vtt \ + -c:v copy -c:a copy \ + -y $@ + emacsconf-%--final.webm: emacsconf-%--main.vtt mux-subs.sh "$@" "$<" emacsconf-%--main.opus: emacsconf-%--main.webm - ffmpeg -y -i "$<" -c:a copy "$@" + AUDIO_CHECK=$$( $(call IS_AUDIO_PRESENT, "$<") ) + if [ ! -z "$$AUDIO_CHECK" ]; then \ + ffmpeg -y -i "$<" -c:a copy "$@"; \ + fi emacsconf-%--reencoded.vtt: emacsconf-%--reencoded.opus whisperx --model large-v3 --align_model WAV2VEC2_ASR_LARGE_LV60K_960H --compute_type int8 --print_progress True --max_line_width 50 --segment_resolution chunk --max_line_count 1 --language en --initial_prompt "Transcribe this talk about Emacs. It may mention Emacs keywords such as Org Mode, Org Roam, Magit, gptel, or chatgpt-shell, or tech keywords such as LLMs. Format function names and keyboard shortcut sequences according to Emacs conventions using Markdown syntax. For example: control h becomes \`C-h\`." "$<" @@ -116,3 +161,38 @@ live-dormant: rsync: rsync -avzue ssh {{ emacsconf_caption_dir }}/cache/ orga@media.emacsconf.org:/var/www/media.emacsconf.org/{{ emacsconf_year }}/backstage/ + + +WAVEFORM_HEIGHT := 240 +WAVEFORM_WIDTH := 400 +WAVEFORM_VOLUME := 3.0 +WAVEFORM_FILTER := "[0:a]aformat=channel_layouts=mono[b];[b]volume=$(WAVEFORM_VOLUME)[a];[a]compand=attacks=0:points=-90/-90|0/0,showwavespic=s=$(WAVEFORM_WIDTH)x$(WAVEFORM_HEIGHT):colors=\#9cf42f[fg];color=s=$(WAVEFORM_WIDTH)x$(WAVEFORM_HEIGHT):color=\#44582c,drawgrid=width=iw/10:height=ih/5:color=\#9cf42f@0.1[bg];[bg][fg]overlay=format=auto[comp];[comp]drawtext=text='$$ID':fontcolor=white:fontsize=24:x=10:y=10:box=1:boxcolor=\#44582c@0.5:boxborderw=5" + +emacsconf-%--backstage--waveform.png: emacsconf-%--normalized.opus + AUDIO_CHECK=$$(ffprobe -loglevel error -select_streams a:0 -show_entries stream=codec_type -of default=noprint_wrappers=1:nokey=1 "$<"); \ + ID=$$(echo "$<" | sed 's/--.*//'); \ + if [ ! -z "$$AUDIO_CHECK" ]; then \ + ffmpeg -i "$<" \ + -filter_complex $(WAVEFORM_FILTER) \ + -frames:v 1 \ + -c:v png \ + -update 1 \ + -y \ + "$@"; \ + fi + +emacsconf-%--backstage--waveform.png: emacsconf-%--reencoded.opus + AUDIO_CHECK=$$(ffprobe -loglevel error -select_streams a:0 -show_entries stream=codec_type -of default=noprint_wrappers=1:nokey=1 "$<"); \ + ID=$$(echo "$<" | sed 's/--.*//'); \ + if [ ! -z "$$AUDIO_CHECK" ]; then \ + ffmpeg -i "$<" \ + -filter_complex $(WAVEFORM_FILTER) \ + -frames:v 1 \ + -c:v png \ + -update 1 \ + -y \ + "$@"; \ + fi + +waveforms.png: $(WAVEFORMS) + convert $^ +append "$@" diff --git a/roles/prerec/templates/reencode-in-screen.sh b/roles/prerec/templates/reencode-in-screen.sh index 5c12203..7119572 100755 --- a/roles/prerec/templates/reencode-in-screen.sh +++ b/roles/prerec/templates/reencode-in-screen.sh @@ -1,7 +1,11 @@ #!/bin/bash ORIGINAL=$1 BASE="${ORIGINAL%--original.*}" -REENCODED="${BASE}--reencoded.webm" +if [ -n "$2" ]; then + REENCODED=$2 +else + REENCODED="${BASE}--reencoded.webm" +fi SLUG=$(echo "$ORIGINAL" | perl -ne '/^emacsconf-[0-9]*-(.*?)--/ && print $1') LOCK=".lock-$SLUG" diff --git a/roles/prerec/templates/talk b/roles/prerec/templates/talk index fa2e5f0..a9d4cb0 100755 --- a/roles/prerec/templates/talk +++ b/roles/prerec/templates/talk @@ -3,6 +3,9 @@ # How to use: talk slug from-status-regexp to-status # or talk slug to-status +# Statuses: +# PLAYING: + SLUG="$1" FROM_STATUS="$2" TO_STATUS="$3" diff --git a/roles/prerec/templates/thumbnail.sh b/roles/prerec/templates/thumbnail.sh index 436979d..1cf7372 100755 --- a/roles/prerec/templates/thumbnail.sh +++ b/roles/prerec/templates/thumbnail.sh @@ -1,3 +1,3 @@ #!/bin/bash # {{ ansible_managed }} -ffmpeg -i "$1" -vf "thumbnail,scale=400:225" -frames:v 1 $(echo "$1" | sed s/webm/png/ ) +ffmpeg -y -i "$1" -vf "thumbnail,scale=400:225" -frames:v 1 $(echo "$1" | sed s/webm/png/ ) diff --git a/roles/publish/tasks/main.yml b/roles/publish/tasks/main.yml index 797ac7f..3ea3784 100644 --- a/roles/publish/tasks/main.yml +++ b/roles/publish/tasks/main.yml @@ -39,10 +39,14 @@ owner: "{{ emacsconf_user }}" group: "{{ emacsconf_group }}" state: directory +- name: Debug + debug: + var: emacs_config_dir - name: Set up Emacs configuration for non-interactive publishing template: src: emacsconf-config.el dest: "{{ emacs_config_dir }}/emacsconf-config.el" + force: yes owner: "{{ emacsconf_user }}" group: "{{ emacsconf_group }}" - name: Check if Emacs base configuration already exists |
