Timelapse: Tagesvideo-Download (ffmpeg/MP4, sonst MJPEG-AVI in reinem Python)
This commit is contained in:
1 parent
304c202f46
commit
13e86bb818
2 files changed
+129
-1
No files matched your search
+26
-1
@@ -124,6 +124,7 @@ const ICONS = {
|
||||
stop: '<rect x="5" y="5" width="14" height="14" rx="2"/>',
|
||||
reload: '<path d="M23 4v6h-6M1 20v-6h6"/><path d="M3.5 9a9 9 0 0 1 14.9-3.4L23 10M1 14l4.6 4.4A9 9 0 0 0 20.5 15"/>',
|
||||
full: '<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>',
|
||||
down: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/>',
|
||||
rec: '<circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3" fill="currentColor"/>',
|
||||
film: '<rect x="2" y="3" width="20" height="18" rx="2"/><path d="M7 3v18M17 3v18M2 8h5M2 16h5M17 8h5M17 16h5"/>',
|
||||
off: '<path d="M1 1l22 22M21 21H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3m3-3h6l2 3h4a2 2 0 0 1 2 2v9.34m-7.72-2.06a4 4 0 1 1-5.56-5.56"/>'
|
||||
@@ -218,7 +219,12 @@ async function openTimelapse(name) {
|
||||
TL_INTERVALS.forEach(v => ivSel.append(new Option("alle " + fmtInterval(v), v)));
|
||||
ivSel.value = tiles[name].tl.interval;
|
||||
ivSel.onchange = () => setTimelapse(name, { interval: +ivSel.value });
|
||||
bar.append(el("h2", "", "Timelapse " + name), daySel, play, ivSel, el("span", "sp"), close);
|
||||
const fpsSel = el("select");
|
||||
fpsSel.title = "Bilder pro Sekunde im Video";
|
||||
[5, 10, 25].forEach(v => fpsSel.append(new Option(v + " fps", v)));
|
||||
fpsSel.value = 10;
|
||||
const video = btn("Video", "down", () => {}, "alt");
|
||||
bar.append(el("h2", "", "Timelapse " + name), daySel, play, ivSel, fpsSel, video, el("span", "sp"), close);
|
||||
bar.querySelector(".sp").style.flex = "1";
|
||||
const body = el("div", "body");
|
||||
tl.replaceChildren(bar, body);
|
||||
@@ -268,6 +274,25 @@ async function openTimelapse(name) {
|
||||
show(files.length - 1);
|
||||
};
|
||||
daySel.onchange = loadDay;
|
||||
video.onclick = async () => {
|
||||
const label = video.querySelector("span");
|
||||
video.disabled = true;
|
||||
label.textContent = "erstelle …";
|
||||
try {
|
||||
const r = await fetch(url(daySel.value, "video") + "?fps=" + fpsSel.value);
|
||||
if (!r.ok) throw new Error(r.status);
|
||||
const a = el("a");
|
||||
a.href = URL.createObjectURL(await r.blob());
|
||||
a.download = (r.headers.get("Content-Disposition") || "").match(/filename="(.+)"/)?.[1] || name + "-" + daySel.value + ".mp4";
|
||||
a.click();
|
||||
setTimeout(() => URL.revokeObjectURL(a.href), 10000);
|
||||
label.textContent = "Video";
|
||||
} catch (e) {
|
||||
label.textContent = "Fehler ✗";
|
||||
setTimeout(() => { label.textContent = "Video"; }, 2500);
|
||||
}
|
||||
video.disabled = false;
|
||||
};
|
||||
play.onclick = () => {
|
||||
if (tlPlay) { const was = play.querySelector("span").textContent === "Pause"; stop(); if (was) return; }
|
||||
play.querySelector("span").textContent = "Pause";
|
||||
|
||||
Reference in new issue
Block a user