Länge von Browser-Aufnahmen ohne Kopfangabe ausmessen
WebM aus dem MediaRecorder nennt oft keine Gesamtlänge; ffprobe liest sie dann aus dem letzten Paket. Videos ohne lesbare Länge werden als Fehler markiert, weil sich ihr Tempo sonst nicht berechnen lässt. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6e497ffc45
commit
18d5b80959
3 files changed
+32
-2
No files matched your search
+21
-2
@@ -16,6 +16,21 @@ function readRotation(stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Länge aus dem Ende des letzten Pakets, wenn der Dateikopf keine nennt.
|
||||
async function measureDuration(file) {
|
||||
const { stdout } = await execFileAsync(
|
||||
'ffprobe',
|
||||
['-v', 'error', '-show_entries', 'packet=pts_time,duration_time', '-of', 'csv=p=0', file],
|
||||
{ maxBuffer: 64 * 1024 * 1024 },
|
||||
);
|
||||
let end = 0;
|
||||
for (const line of stdout.split('\n')) {
|
||||
const [pts, duration] = line.split(',').map(Number);
|
||||
if (Number.isFinite(pts)) end = Math.max(end, pts + (Number.isFinite(duration) ? duration : 0));
|
||||
}
|
||||
return end > 0 ? end : null;
|
||||
}
|
||||
|
||||
// Liefert die Eckdaten einer Video- oder Audiodatei; Breite und Höhe so,
|
||||
// wie das Video angezeigt wird.
|
||||
export async function probe(file) {
|
||||
@@ -28,10 +43,14 @@ export async function probe(file) {
|
||||
const video = info.streams.find(
|
||||
(stream) => stream.codec_type === 'video' && !stream.disposition?.attached_pic,
|
||||
);
|
||||
const hasAudio = info.streams.some((stream) => stream.codec_type === 'audio');
|
||||
const audio = info.streams.find((stream) => stream.codec_type === 'audio');
|
||||
const hasAudio = Boolean(audio);
|
||||
if (!video && !hasAudio) throw new Error('Weder Bild noch Ton gefunden.');
|
||||
|
||||
const duration = Number(info.format?.duration ?? video?.duration ?? 0);
|
||||
// Browser-Aufnahmen (WebM) tragen oft keine Gesamtlänge im Kopf.
|
||||
const duration =
|
||||
[info.format?.duration, video?.duration, audio?.duration].map(Number).find(Number.isFinite) ??
|
||||
(await measureDuration(file));
|
||||
if (!video) {
|
||||
return { duration, hasVideo: false, width: null, height: null, rotation: 0, fps: 0, hasAudio };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user