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>
67 lines
2.5 KiB
JavaScript
67 lines
2.5 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { execFileSync } from 'node:child_process';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { after, before, test } from 'node:test';
|
|
import { probe } from '../server/media.js';
|
|
|
|
const hasFfmpeg = (() => {
|
|
try {
|
|
execFileSync('ffmpeg', ['-version'], { stdio: 'ignore' });
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
})();
|
|
|
|
let dir;
|
|
|
|
before(() => {
|
|
if (!hasFfmpeg) return;
|
|
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fdc-media-'));
|
|
const ffmpeg = (...args) => execFileSync('ffmpeg', ['-v', 'error', '-y', ...args]);
|
|
ffmpeg('-f', 'lavfi', '-i', 'testsrc=size=320x180:rate=25', '-f', 'lavfi', '-i', 'sine', '-t', '2',
|
|
'-c:v', 'libx264', '-c:a', 'aac', '-shortest', path.join(dir, 'quer.mp4'));
|
|
// Wie ein Hochkant-Handyvideo: quer gespeichert, mit Drehung im Dateikopf
|
|
ffmpeg('-i', path.join(dir, 'quer.mp4'), '-an', '-c', 'copy', '-metadata:s:v:0', 'rotate=90',
|
|
path.join(dir, 'hochkant.mp4'));
|
|
// Wie eine Browser-Aufnahme: WebM ohne Gesamtlänge im Kopf
|
|
ffmpeg('-f', 'lavfi', '-i', 'sine', '-t', '2', '-c:a', 'libopus', '-f', 'webm', '-live', '1',
|
|
path.join(dir, 'aufnahme.webm'));
|
|
});
|
|
|
|
after(() => {
|
|
if (dir) fs.rmSync(dir, { recursive: true, force: true });
|
|
});
|
|
|
|
test('ffprobe liefert Länge, Größe, Bildrate und Tonspur', { skip: !hasFfmpeg && 'ffmpeg fehlt' }, async () => {
|
|
const media = await probe(path.join(dir, 'quer.mp4'));
|
|
assert.ok(Math.abs(media.duration - 2) < 0.1);
|
|
assert.equal(media.width, 320);
|
|
assert.equal(media.height, 180);
|
|
assert.equal(media.fps, 25);
|
|
assert.equal(media.hasAudio, true);
|
|
});
|
|
|
|
test('Gedrehte Videos werden hochkant erkannt', { skip: !hasFfmpeg && 'ffmpeg fehlt' }, async () => {
|
|
const media = await probe(path.join(dir, 'hochkant.mp4'));
|
|
assert.equal(Math.abs(media.rotation), 90);
|
|
assert.equal(media.width, 180);
|
|
assert.equal(media.height, 320);
|
|
assert.equal(media.hasAudio, false);
|
|
});
|
|
|
|
test('Datei ohne Video wird abgelehnt', { skip: !hasFfmpeg && 'ffmpeg fehlt' }, async () => {
|
|
const file = path.join(dir, 'text.mp4');
|
|
fs.writeFileSync(file, 'kein Video');
|
|
await assert.rejects(probe(file));
|
|
});
|
|
|
|
test('Browser-Aufnahme ohne Längenangabe wird ausgemessen', { skip: !hasFfmpeg && 'ffmpeg fehlt' }, async () => {
|
|
const media = await probe(path.join(dir, 'aufnahme.webm'));
|
|
assert.equal(media.hasVideo, false);
|
|
assert.equal(media.hasAudio, true);
|
|
assert.ok(Math.abs(media.duration - 2) < 0.1, `Länge ${media.duration}`);
|
|
});
|