Projekte anlegen und Clips in Stücken hochladen
Ein Projekt hält die ausgewählten Clips samt Absender und Beschriftung. Videos kommen in Stücken bis 16 MB; die Größe der Teildatei ist der Stand, sodass ein abgebrochener Upload dort weitermacht. Nach dem letzten Stück liest ffprobe Länge, Größe, Drehung und Tonspur aus. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6f583c8f5b
commit
782d306cb1
7 files changed
+549
-2
No files matched your search
@@ -0,0 +1,42 @@
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
function parseRate(rate) {
|
||||
const [numerator, denominator] = String(rate || '0/1').split('/').map(Number);
|
||||
return denominator ? numerator / denominator : 0;
|
||||
}
|
||||
|
||||
// Handyvideos liegen oft quer im Container und tragen die Drehung als Metadatum.
|
||||
function readRotation(stream) {
|
||||
const side = stream.side_data_list?.find((entry) => entry.rotation !== undefined);
|
||||
if (side) return Number(side.rotation);
|
||||
if (stream.tags?.rotate) return Number(stream.tags.rotate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Liefert die Eckdaten eines Videos, Breite und Höhe so, wie es angezeigt wird.
|
||||
export async function probe(file) {
|
||||
const { stdout } = await execFileAsync(
|
||||
'ffprobe',
|
||||
['-v', 'error', '-print_format', 'json', '-show_streams', '-show_format', file],
|
||||
{ maxBuffer: 10 * 1024 * 1024 },
|
||||
);
|
||||
const info = JSON.parse(stdout);
|
||||
const video = info.streams.find(
|
||||
(stream) => stream.codec_type === 'video' && !stream.disposition?.attached_pic,
|
||||
);
|
||||
if (!video) throw new Error('Keine Videospur gefunden.');
|
||||
|
||||
const rotation = readRotation(video);
|
||||
const sideways = Math.abs(rotation) % 180 === 90;
|
||||
return {
|
||||
duration: Number(info.format?.duration ?? video.duration ?? 0),
|
||||
width: sideways ? video.height : video.width,
|
||||
height: sideways ? video.width : video.height,
|
||||
rotation,
|
||||
fps: Math.round(parseRate(video.avg_frame_rate || video.r_frame_rate) * 100) / 100,
|
||||
hasAudio: info.streams.some((stream) => stream.codec_type === 'audio'),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user