summaryrefslogtreecommitdiffstats
path: root/roles/prerec/templates/Makefile
blob: 778ae3efd2d217df227314727cb1efa1fabe933e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# {{ ansible_managed }}

# To recreate this file, use ansible-playbook -i inventory.yml prod-playbook.yml --tags prerec-make

.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 main-opus waveforms.png

reencoded: $(PRERECS_REENCODED)

opus: $(PRERECS_OPUS)

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)))))
	@if [ -z "$(SOURCE)" ]; then \
		echo "No source file found for $@"; \
		echo "Tried: $(SOURCES)"; \
		exit 1; \
	fi
	@echo "Using source: $(SOURCE)"
	reencode-in-screen.sh "$(SOURCE)"

emacsconf-%--reencoded.opus: emacsconf-%--reencoded.webm
	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 "$@"

# emacsconf-%--normalized.opus: emacsconf-%--reencoded.opus
# 	ffmpeg-normalize "$<" -ofmt opus -c:a libopus -o "$@"

emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--normalized.opus emacsconf-%--main.vtt
	ffmpeg -i emacsconf-$*--reencoded.webm -i emacsconf-$*--normalized.opus -i emacsconf-$*--main.vtt \
		-map 0:v -map 1:a -c:v copy -c:a copy \
		-map 2 -c:s webvtt -y \
		$@

emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--normalized.opus
	ffmpeg -i emacsconf-$*--reencoded.webm -i emacsconf-$*--normalized.opus \
		-map 0:v -map 1:a -c:v copy -c:a copy \
    -y $@

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
	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\`." "$<"

emacsconf-%--backstage--silences.csv: emacsconf-%--reencoded.opus
	ffmpeg -i "$<" -af silencedetect=noise=-30dB:d=0.5 -f null - 2>&1 | awk '/silence_start/ {start=$$NF} /silence_end/ {print start "," (start + $$NF)}' > "$@"

show-files:
	@echo "Original $(words $(PRERECS_ORIGINAL)):"
	@echo "$(PRERECS_ORIGINAL)"
	@echo "Prefixes $(words $(PREFIXES)):"
	@echo "$(PREFIXES)"
	@echo "Reencoded $(words $(PRERECS_REENCODED)):"
	@echo "$(PRERECS_REENCODED)"
	@echo "Opus $(words $(PRERECS_OPUS)):"
	@echo "$(PRERECS_OPUS)"

bbb-testing:
	@echo "Resizing BBB node to 8GB 4 core for testing"
	linode-cli linodes resize $(LINODE_BBB_ID) --type g6-standard-4 --allow_auto_disk_resize false
	sleep 2m
	@echo "Booting up"
	linode-cli linodes boot $(LINODE_BBB_ID)
	ssh root@bbb.emacsverse.org "cd ~/greenlight-v3; docker compose restart"

bbb-dormant:
	@echo "Shutting down"
	ssh root@bbb.emacsverse.org "/usr/sbin/shutdown -h now &" || true
	sleep 30
	@echo "Powering off BBB node"
	linode-cli linodes shutdown $(LINODE_BBB_ID)
	sleep 30
	@echo "Resizing BBB node to nanode, dormant"
	linode-cli linodes resize $(LINODE_BBB_ID) --type g6-nanode-1 --allow_auto_disk_resize false

bbb-prod:
	@echo "Resizing BBB node to production size"
	linode-cli linodes resize $(LINODE_BBB_ID) --type g6-dedicated-8 --allow_auto_disk_resize true
	sleep 2m
	@echo "Booting up"
	linode-cli linodes boot $(LINODE_BBB_ID)

live-dormant:
	@echo "Resizing live0 node to nanode, dormant"
	linode-cli linodes resize 17921960 --type g6-nanode-1 --allow_auto_disk_resize false
	sleep 120
	linode-cli linodes boot 17921960


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 "$@"