Initial commit
This commit is contained in:
commit
e612344d5e
35
README.md
Normal file
35
README.md
Normal file
@ -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
|
62
dziurkacz.mjs
Normal file
62
dziurkacz.mjs
Normal file
@ -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`
|
||||
);
|
18
macro.ny
Normal file
18
macro.ny
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user