From e612344d5e880c996b5f71b1d982325c9ec313cb Mon Sep 17 00:00:00 2001 From: Kuba Orlik Date: Sun, 12 Sep 2021 19:38:48 +0200 Subject: [PATCH] Initial commit --- README.md | 35 +++++++++++++++++++++++++++++ dziurkacz.mjs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ macro.ny | 18 +++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 README.md create mode 100644 dziurkacz.mjs create mode 100644 macro.ny diff --git a/README.md b/README.md new file mode 100644 index 0000000..e19cba4 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Dziurkacz + +Zestaw narzędzi pomagający wyciąć z pliku wideo te same fragmenty, które zostały wycięte z pliku audio. + +## Wyamgania + +- ffmpeg, +- Audacity, +- zx (https://github.com/google/zx) + +## Instalacja + +### Macro do Audacity + +1. W Audacity utwórz makro z jednym krokiem. + +2. Ustaw typ kroku: Nyquist Prompt + +3. Kliknij `Edit` + +4. Wklej do okienka dialogowego zawartość pliku `macro.ny` z niniejszego repozytorium + +Następnie przypisz to makro do skrótu klawiaturowego (np. ctrl+d). + +Odpalenie tego makro usunie zaznaczony fragment ścieżki i zapisze w labelce informacje o długości usuniętego fragmentu i jego pozycji w ścieżce + +## Używanie + +1. Otwórz plik dźwiękowy z video w Audacity i usuwaj fragmenty za pomocą makra opisanego powyżej. + +2. Wyeksportuj wszystkie labelki do pliku tekstowego (export -> labels) + +3. Uruchom `zx --quiet dziurkacz.mjs /ścieżka/do/pliku/video.mp4 /ścieżka/do/pliku/z/wyeskportowanymi/labelkami.txt` + +Plik wynikowy znajdziesz w /tmp/dziurkacz/working.mp4 diff --git a/dziurkacz.mjs b/dziurkacz.mjs new file mode 100644 index 0000000..9f13990 --- /dev/null +++ b/dziurkacz.mjs @@ -0,0 +1,62 @@ +import { extname } from "path"; + +const args = process.argv.slice(-2); + +const video = args[0]; +const labels = args[1]; +const ext = extname(video); + +const labels_contents = (await $`awk '{print $3, $4, $5}' < ${labels}`).stdout; + +const FREQ = 48000; + +const working_dir = "/tmp/dziurkacz"; + +const before_path = `${working_dir}/before${ext}`; +const after_path = `${working_dir}/after${ext}`; +const working_path = `${working_dir}/working${ext}`; +const vdlist = `${working_dir}/vdlist.txt`; + +async function makeCut({ duration, start, end }) { + await Promise.all([ + $`ffmpeg -i ${working_path} -to ${start} -c copy -an -y ${before_path}`, + $`ffmpeg -ss ${end} -i ${working_path} -c copy -an -y ${after_path}`, + ]); + await Promise.all([ + $`echo file ${before_path} > ${vdlist}`, + $`echo file ${after_path} >> ${vdlist}`, + ]); + await $`ffmpeg -f concat -safe 0 -i ${vdlist} -c copy -y ${working_path} `; +} + +await $`mkdir -p ${working_dir}`; +await $`cp -f ${video} ${working_path}`; + +const cuts = labels_contents + .split(os.EOL) + .slice(0, -1) + .map((e) => + e + .split(" ") + .slice(1) + .map((x) => parseFloat(x)) + ) + .map(([samples, start]) => ({ + duration: samples / FREQ, + start, + end: start + samples / FREQ, + })); + +// await makeCut(cuts[0]); +// await makeCut(cuts[1]); + +for (const cut of cuts) { + await makeCut(cut); +} + +console.log( + `Removed ${cuts + .map((e) => e.duration) + .reduce((a, b) => a + b, 0) + .toFixed(3)}s from video` +); diff --git a/macro.ny b/macro.ny new file mode 100644 index 0000000..13d3524 --- /dev/null +++ b/macro.ny @@ -0,0 +1,18 @@ +(aud-do "AddLabel:") + +(setf labels (car (cdr (car (aud-get-info "Labels"))))) + +(setf amount-of-labels (length labels)) + +(setf last-label (cdr labels)) + +(setf label-index (- amount-of-labels 1)) +(setf label-index (cond ((= label-index -1) 0) (t label-index))) + +(print label-index) + +(aud-do-command "SetLabel" :text (format nil "~A ~A ~S" amount-of-labels LEN (get '*selection* 'start)) :label (- amount-of-labels 1) :start 0 :end 0) + +(aud-do-command "Delete") + +NIL \ No newline at end of file