diff --git a/.gitignore b/.gitignore index 4586756..9241222 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.mp4 out/* !out/keepme +*.wav +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/demux.sh b/demux.sh deleted file mode 100644 index c268cbf..0000000 --- a/demux.sh +++ /dev/null @@ -1,9 +0,0 @@ -echo "generating the demuxers..." - -# generuje ścieżki do złożenia przez ffmpega: -ts-node generate-demuxer.ts >out/demuxer.txt - -# używa demuxer.txt żeby skleić końcowe video z dźwiękiem: -echo generowanie całości -ffmpeg -y -f concat -safe 0 -i out/demuxer.txt -r $framerate -video_track_timescale $timescale -tune stillimage -pix_fmt yuv420p out/video.mp4 -# ^ daję safe 0 aby przyjmowało bezwzględne ścieżki diff --git a/find-loudness.ts b/find-loudness.ts old mode 100644 new mode 100755 diff --git a/generate-demuxer.ts b/generate-demuxer.ts old mode 100644 new mode 100755 index 1b3b2a7..2f666a3 --- a/generate-demuxer.ts +++ b/generate-demuxer.ts @@ -2,9 +2,7 @@ import findLoudness, { SwapPoint } from "./find-loudness"; const graph_density = 8000; -const threshold_at_point = parseInt( - process.env.demuxer_volume_threshold || "1" -); +const threshold_at_point = 2; const inertia_s = 0.3; const inertia_samples = inertia_s * graph_density; @@ -16,65 +14,75 @@ const minutes = (units: number) => Math.floor(s(units) / 60); const hours = (units: number) => Math.floor(units / graph_density / 60 / 60); const formatTime = (units: number) => - `${hours(units)}:${minutes(units)}:${Math.floor(s(units) % 60)}`; + `${hours(units)}:${minutes(units)}:${Math.floor(s(units) % 60)}`; type Mode = { left: boolean; right: boolean }; async function run() { - const [left_breaks, right_breaks] = await Promise.all([ - findLoudness("/tmp/leftraw", threshold_at_point, inertia_samples, "left"), - findLoudness("/tmp/rightraw", threshold_at_point, inertia_samples, "right"), - ]); + const [left_breaks, right_breaks] = await Promise.all([ + findLoudness( + "/tmp/leftraw", + threshold_at_point, + inertia_samples, + "left" + ), + findLoudness( + "/tmp/rightraw", + threshold_at_point, + inertia_samples, + "right" + ), + ]); - const merged = [...left_breaks, ...right_breaks].sort((a, b) => - a.position_start < b.position_start - ? -1 - : a.position_start > b.position_start - ? 1 - : 0 - ); + const merged = [...left_breaks, ...right_breaks].sort((a, b) => + a.position_start < b.position_start + ? -1 + : a.position_start > b.position_start + ? 1 + : 0 + ); - // console.log("left breaks:", left_breaks); - // console.log(`right_breaks`, right_breaks); - // console.log(`merged`, merged); + // console.log("left breaks:", left_breaks); + // console.log(`right_breaks`, right_breaks); + // console.log(`merged`, merged); - function new_mode(m: Mode, s: SwapPoint): Mode { - return { ...m, [s.label]: s.loud }; - } + function new_mode(m: Mode, s: SwapPoint): Mode { + return { ...m, [s.label]: s.loud }; + } - function mode_to_string(mode: Mode) { - if (mode.left && mode.right) { - return "both"; - } - for (const side of ["left", "right"]) { - if (mode[side as keyof Mode]) { - return side; - } - } - return "none"; - } + function mode_to_string(mode: Mode) { + if (mode.left && mode.right) { + return "both"; + } + for (const side of ["left", "right"]) { + if (mode[side as keyof Mode]) { + return side; + } + } + return "none"; + } - console.log("file", `${process.cwd()}/pics/none.png`); - let last_point = 0; - let mode: Mode = { left: false, right: false }; - let last_file; - let total = 0; - for (let i = 2; i < merged.length; i++) { - const point = merged[i]; - mode = new_mode(mode, point); - const file = `${process.cwd()}/pics/${mode_to_string(mode)}.png`; - const duration = (point.position_start - last_point) / graph_density; - console.log( - "duration", - (point.position_start - last_point) / graph_density - ); - console.log("file", file); - last_point = point.position_start; - last_file = file; - total += duration * graph_density; - } - console.log("duration", merged[merged.length - 1].duration / graph_density); - console.log("file", last_file); - console.error(total, formatTime(total)); + console.log("file", `${process.cwd()}/pics/none.png`); + let last_point = 0; + let mode: Mode = { left: false, right: false }; + let last_file; + let total = 0; + for (let i = 2; i < merged.length; i++) { + const point = merged[i]; + mode = new_mode(mode, point); + const file = `${process.cwd()}/pics/${mode_to_string(mode)}.png`; + const duration = (point.position_start - last_point) / graph_density; + console.log( + "duration", + (point.position_start - last_point) / graph_density + ); + console.log("file", file); + last_point = point.position_start; + last_file = file; + total += duration * graph_density; + } + console.log("duration", merged[merged.length - 1].duration / graph_density); + console.log("file", last_file); + console.error(total, formatTime(total)); } run(); diff --git a/generate.sh b/generate.sh index c1e966f..a0cf655 100755 --- a/generate.sh +++ b/generate.sh @@ -6,18 +6,34 @@ # W katalogu z tym skryptem musisz mieć katalog "pics", w którym są pliki "left.png", "right.png", "none.png" i "both.png" # -export input=~/Downloads/icdw5/icdw5-stereo.wav # tutaj dajemy ścieżkę do pliku mp3 z Arkiem w jednym kanale i Kubą w drugim -export input_mono=~/Downloads/icdw5/icdw5-stereo.wav # tutaj dajemy ścieżkę do pliku mp3 z Arkiem w jednym kanale i Kubą w drugim -export intro=~/projects/midline/podcast-visualizer/out/intro.mp4 # glitch -export outro=~/projects/midline/podcast-visualizer/out/intro.mp4 # to samo na końcu, co na początku -export final_output=~/Downloads/icdw5-viz.mp4 -export framerate=25 -export timescale=25000 -export demuxer_volume_threshold=15 #od 0 do 128 +framerate=60 +timescale=25000 + +aresample=8000 # to bez zmian + +# echo dzielimy mp3 na dwa osobne wav +# ffmpeg -i $input -map_channel 0.0.0 /tmp/left.wav -map_channel 0.0.1 /tmp/right.wav + + +ffmpeg -i ./left.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - > /tmp/leftraw & +ffmpeg -i ./right.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - > /tmp/rightraw & + +# czekamy aż obydwa wątki się zakończą +wait; + +echo "generating the demuxers..."; + +# generuje ścieżki do złożenia przez ffmpega: +ts-node generate-demuxer.ts > out/demuxer.txt -aresample=8000 # to bez zmian mkdir -p out -source ./split.sh -source ./demux.sh -source ./merge.sh +# używa demuxer.txt żeby skleić końcowe video z dźwiękiem: +echo generowanie całości +# ffmpeg -y -f concat -safe 0 -i out/demuxer.txt -r $framerate -video_track_timescale $timescale -tune stillimage -fps_mode vfr -pix_fmt yuv420p out/video.mp4 +ffmpeg -y -f concat -safe 0 -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -i out/demuxer.txt -r $framerate -video_track_timescale $timescale -tune stillimage -pix_fmt yuv420p out/video.mp4 +# ^ daję safe 0 aby przyjmowało bezwzględne ścieżki + + +# echo łączenie video z dźwiękiem: +# ffmpeg -i out/video.mp4 -i $input -ac 1 -video_track_timescale $timescale -tune stillimage out/video-and-audio.mp4 diff --git a/merge.sh b/merge.sh deleted file mode 100755 index 17bcafa..0000000 --- a/merge.sh +++ /dev/null @@ -1,44 +0,0 @@ -processed_intro_path=$PWD/out/intro-processed.mp4 -processed_outro_path=$PWD/out/outro-processed.mp4 - -echo łączenie video z dźwiękiem: -ffmpeg -y -vaapi_device /dev/dri/renderD128 \ - -i out/video.mp4 -i $input_mono \ - -video_track_timescale $timescale \ - -tune stillimage \ - -c:a aac \ - -ac 1 \ - -strict experimental \ - -vf 'format=nv12,hwupload' \ - -c:v h264_vaapi \ - out/video-and-audio.mp4 - -echo reencoding intro to enable fast concat... - -function reencode_for_demux_compatibility() { - ffmpeg -y -i "$1" \ - -pix_fmt yuv420p \ - -r $framerate \ - -video_track_timescale $timescale \ - -ac 1 \ - -b:a 320k \ - "$2" - -} - -reencode_for_demux_compatibility "$intro" "$processed_intro_path" - -if [ "$intro" = "$outro" ]; then - processed_outro_path="$processed_intro_path" -else - reencode_for_demux_compatibility "$outro" "$processed_outro_path" -fi - -echo "" >out/demuxer-branding.txt -echo "file $processed_intro_path" >>out/demuxer-branding.txt -echo "file video-and-audio.mp4" >>out/demuxer-branding.txt -echo "file $processed_outro_path" >>out/demuxer-branding.txt - -cat out/demuxer-branding.txt - -ffmpeg -y -f concat -safe 0 -i out/demuxer-branding.txt -c:v copy -b:a 320k "$final_output" diff --git a/out/keepme b/out/keepme deleted file mode 100644 index e69de29..0000000 diff --git a/package-lock.json b/package-lock.json old mode 100644 new mode 100755 diff --git a/package.json b/package.json old mode 100644 new mode 100755 diff --git a/pics/both.png b/pics/both.png old mode 100644 new mode 100755 index 199dca3..f3f526b Binary files a/pics/both.png and b/pics/both.png differ diff --git a/pics/left.png b/pics/left.png old mode 100644 new mode 100755 index 9bfb28a..3e1584d Binary files a/pics/left.png and b/pics/left.png differ diff --git a/pics/none.png b/pics/none.png old mode 100644 new mode 100755 index 1a6ab25..001bb30 Binary files a/pics/none.png and b/pics/none.png differ diff --git a/pics/right.png b/pics/right.png old mode 100644 new mode 100755 index 9f891d3..b2c4a76 Binary files a/pics/right.png and b/pics/right.png differ diff --git a/split.sh b/split.sh deleted file mode 100644 index ae26675..0000000 --- a/split.sh +++ /dev/null @@ -1,9 +0,0 @@ -echo dzielimy mp3 na dwa osobne wav -ffmpeg -y -i $input -map_channel 0.0.0 /tmp/left.wav -map_channel 0.0.1 /tmp/right.wav - -echo na dwóch wątkach generujemy surowe pliki -ffmpeg -y -i /tmp/left.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - >/tmp/leftraw & -ffmpeg -y -i /tmp/right.wav -ac 1 -filter:a aresample=$aresample -map 0:a -c:a pcm_u8 -f data - >/tmp/rightraw & - -# czekamy aż obydwa wątki się zakończą -wait diff --git a/tsconfig.json b/tsconfig.json old mode 100644 new mode 100755 diff --git a/window.ts b/window.ts old mode 100644 new mode 100755