mirror-immich/server/test/fixtures/media.stub.ts

618 lines
17 KiB
TypeScript

import {
AacProfile,
ColorMatrix,
ColorPrimaries,
ColorTransfer,
DvProfile,
DvSignalCompatibility,
H264Profile,
HevcProfile,
} from 'src/enum';
import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/types';
const probeStubDefaultFormat: VideoFormat = {
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
formatLongName: 'QuickTime / MOV',
duration: 0,
bitrate: 0,
};
const probeStubDefaultVideoStream: VideoStreamInfo[] = [
{
index: 0,
height: 1080,
width: 1920,
codecName: 'hevc',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
];
const probeStubDefaultAudioStream: AudioStreamInfo[] = [{ index: 3, codecName: 'mp3', bitrate: 100, profile: null }];
const probeStubDefault: VideoInfo = {
format: probeStubDefaultFormat,
videoStreams: probeStubDefaultVideoStream,
audioStreams: probeStubDefaultAudioStream,
};
/** Fixtures in the shape `mediaRepository.probe()` returns (arrays of streams, raw ffprobe format). */
export const videoInfoStub = {
noVideoStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, videoStreams: [] }),
noAudioStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, audioStreams: [] }),
multipleVideoStreams: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 1,
height: 1080,
width: 400,
codecName: 'hevc',
frameCount: 2,
rotation: 0,
bitrate: 101,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
{
index: 0,
height: 1080,
width: 400,
codecName: 'hevc',
frameCount: 1,
rotation: 0,
bitrate: 100,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
{
index: 2,
height: 1080,
width: 400,
codecName: 'h7000',
frameCount: 3,
rotation: 0,
bitrate: 99,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
multipleAudioStreams: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{ index: 2, codecName: 'mp3', bitrate: 102, profile: null },
{ index: 1, codecName: 'mp3', bitrate: 101, profile: null },
{ index: 0, codecName: 'mp3', bitrate: 100, profile: null },
],
}),
noHeight: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 0,
width: 400,
codecName: 'hevc',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStream2160p: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: HevcProfile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStream40Mbps: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], bitrate: 40_000_000, codecName: 'h264' }],
}),
videoStreamMTS: Object.freeze<VideoInfo>({
...probeStubDefault,
format: {
formatName: 'mpegts',
formatLongName: 'MPEG-TS (MPEG-2 Transport Stream)',
duration: 0,
bitrate: 0,
},
}),
videoStreamHDR: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 480,
width: 480,
codecName: 'h264',
frameCount: 100,
rotation: 0,
colorPrimaries: ColorPrimaries.Bt2020,
colorMatrix: ColorMatrix.Bt2020Nc,
colorTransfer: ColorTransfer.Smpte2084,
bitrate: 0,
pixelFormat: 'yuv420p10le',
frameRate: 60,
timeBase: 600,
profile: H264Profile.High10,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStream10Bit: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 480,
width: 480,
codecName: 'h264',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p10le',
frameRate: 60,
timeBase: 600,
profile: H264Profile.High10,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStream4K10Bit: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p10le',
frameRate: 60,
timeBase: 600,
profile: H264Profile.High10,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStreamVertical2160p: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 90,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: H264Profile.High,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStreamOddHeight: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 355,
width: 1586,
codecName: 'h264',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: H264Profile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStreamOddWidth: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 1586,
width: 355,
codecName: 'h264',
frameCount: 100,
rotation: 0,
bitrate: 0,
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
pixelFormat: 'yuv420p',
frameRate: 60,
timeBase: 600,
profile: H264Profile.Main,
level: null,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
audioStreamAac: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [{ index: 1, codecName: 'aac', bitrate: 100, profile: AacProfile.Lc }],
}),
audioStreamMp3: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [{ index: 1, codecName: 'mp3', bitrate: 100, profile: null }],
}),
audioStreamOpus: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [{ index: 1, codecName: 'opus', bitrate: 100, profile: null }],
}),
audioStreamUnknown: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{ index: 0, codecName: 'aac', bitrate: 100, profile: AacProfile.Lc },
{ index: 1, codecName: 'unknown', bitrate: 200, profile: null },
],
}),
matroskaContainer: Object.freeze<VideoInfo>({
...probeStubDefault,
format: {
formatName: 'matroska,webm',
formatLongName: 'Matroska / WebM',
duration: 0,
bitrate: 0,
},
}),
videoStreamVp9: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'vp9' }],
format: {
formatName: 'matroska,webm',
formatLongName: 'Matroska / WebM',
duration: 0,
bitrate: 0,
},
}),
videoStreamH264: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'h264' }],
}),
videoStreamAvi: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'h264' }],
format: {
formatName: 'avi',
formatLongName: 'AVI (Audio Video Interleaved)',
duration: 0,
bitrate: 0,
},
}),
videoStreamReserved: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
...probeStubDefaultVideoStream[0],
colorPrimaries: ColorPrimaries.Reserved,
colorMatrix: ColorMatrix.Reserved,
colorTransfer: ColorTransfer.Reserved,
},
],
}),
videoStreamHDR10: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'hevc',
profile: 2,
level: 153,
frameCount: 1208,
frameRate: 59.94,
rotation: 0,
bitrate: 64_000_000,
pixelFormat: 'yuv420p10le',
colorPrimaries: ColorPrimaries.Bt2020,
colorMatrix: ColorMatrix.Bt2020Nc,
colorTransfer: ColorTransfer.Smpte2084,
timeBase: 600,
dvBlSignalCompatibilityId: null,
dvLevel: null,
dvProfile: null,
},
],
}),
videoStreamDolbyVision: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'hevc',
profile: 2,
level: 153,
frameCount: 1299,
frameRate: 59.94,
rotation: 0,
bitrate: 53_500_000,
pixelFormat: 'yuv420p10le',
colorPrimaries: ColorPrimaries.Bt2020,
colorMatrix: ColorMatrix.Bt2020Nc,
colorTransfer: ColorTransfer.AribStdB67,
dvProfile: DvProfile.Dvhe08,
dvLevel: 10,
dvBlSignalCompatibilityId: DvSignalCompatibility.Hlg,
timeBase: 600,
},
],
}),
videoStreamWithProfileLevel: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
...probeStubDefaultVideoStream[0],
codecName: 'h264',
profile: 100,
level: 40,
},
],
}),
audioStreamAAC: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{
index: 1,
codecName: 'aac',
profile: 2,
bitrate: 128_000,
},
],
}),
};
interface SelectedStreams {
videoStream: VideoStreamInfo & { timeBase: number };
audioStream: AudioStreamInfo | null;
format: VideoFormat;
}
const toSelectedStreams = (info: VideoInfo) => ({
videoStream: info.videoStreams[0] ?? null,
audioStream: info.audioStreams[0] ?? null,
format: info.format,
});
export const probeStub = Object.fromEntries(
Object.entries(videoInfoStub).map(([key, info]) => [key, toSelectedStreams(info)]),
) as Record<keyof typeof videoInfoStub, SelectedStreams>;
export const eiffelTower = {
originalPath: 'eiffel-tower.mp4',
videoStream: {
index: 0,
width: 1080,
height: 1920,
rotation: 0,
codecName: 'h264',
profile: H264Profile.High,
level: 40,
frameCount: 557,
frameRate: 24.908_004_845_459_07,
timeBase: 90_000,
bitrate: 5_128_622,
pixelFormat: 'yuv420p',
colorPrimaries: ColorPrimaries.Smpte170M,
colorTransfer: ColorTransfer.Smpte170M,
colorMatrix: ColorMatrix.Smpte170M,
dvProfile: null,
dvLevel: null,
dvBlSignalCompatibilityId: null,
},
audioStream: { codecName: 'aac', bitrate: 125_629, index: 1, profile: AacProfile.Lc },
packets: {
totalDuration: 2_012_441,
packetCount: 557,
outputFrames: 557,
keyframePts: [0, 462_502, 925_004, 1_210_454, 1_387_506, 1_542_878, 1_850_008],
keyframeAccDuration: [3613, 466_077, 928_541, 1_213_968, 1_391_005, 1_546_364, 1_853_469],
keyframeOwnDuration: [3613, 3613, 3613, 3613, 3613, 3613, 3613],
},
format: {
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
formatLongName: 'QuickTime / MOV',
duration: 22_616,
bitrate: 5_128_622,
},
};
export const waterfall = {
originalPath: 'waterfall.mp4',
videoStream: {
index: 2,
width: 3840,
height: 2160,
rotation: -90,
codecName: 'hevc',
profile: HevcProfile.Main,
level: 156,
frameCount: 309,
frameRate: 29.829_901_982_867_92,
timeBase: 90_000,
bitrate: 43_363_499,
pixelFormat: 'yuvj420p',
colorPrimaries: ColorPrimaries.Bt709,
colorTransfer: ColorTransfer.Bt709,
colorMatrix: ColorMatrix.Bt709,
dvProfile: null,
dvLevel: null,
dvBlSignalCompatibilityId: null,
},
audioStream: { codecName: 'aac', bitrate: 191_878, index: 1, profile: null },
packets: {
totalDuration: 932_286,
packetCount: 309,
outputFrames: 309,
keyframePts: [0, 89_987, 179_974, 269_961, 359_948, 449_936, 539_923, 629_910, 725_166, 815_273, 905_295],
keyframeAccDuration: [
2999, 92_987, 182_974, 272_961, 362_948, 452_934, 542_922, 632_909, 728_175, 818_274, 908_296,
],
keyframeOwnDuration: [2999, 3000, 3000, 3000, 3000, 2998, 2999, 2999, 3009, 3001, 3001],
},
format: {
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
formatLongName: 'QuickTime / MOV',
duration: 10_359,
bitrate: 43_363_499,
},
};
export const train = {
originalPath: 'train.mov',
videoStream: {
index: 0,
width: 1920,
height: 1080,
rotation: -90,
codecName: 'hevc',
profile: HevcProfile.Main10,
level: 123,
frameCount: 1229,
frameRate: 56.536_072_989_342_94,
timeBase: 600,
bitrate: 12_595_191,
pixelFormat: 'yuv420p10le',
colorPrimaries: ColorPrimaries.Bt2020,
colorTransfer: ColorTransfer.AribStdB67,
colorMatrix: ColorMatrix.Bt2020Nc,
dvProfile: DvProfile.Dvhe08,
dvLevel: 5,
dvBlSignalCompatibilityId: DvSignalCompatibility.Hlg,
},
audioStream: { codecName: 'aac', bitrate: 175_477, index: 1, profile: AacProfile.Lc },
packets: {
totalDuration: 12_290,
packetCount: 1229,
outputFrames: 1304,
keyframePts: [
0, 601, 1201, 1802, 2402, 3003, 3604, 4204, 4805, 5405, 6006, 6607, 7207, 7808, 8408, 9009, 9609, 10_210, 10_811,
11_411, 12_062, 12_703,
],
keyframeAccDuration: [
10, 580, 1180, 1780, 2380, 2980, 3580, 4180, 4780, 5380, 5980, 6580, 7180, 7780, 8380, 8980, 9580, 10_180, 10_780,
11_380, 11_780, 12_100,
],
keyframeOwnDuration: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
},
format: {
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
formatLongName: 'QuickTime / MOV',
duration: 21_738,
bitrate: 12_595_191,
},
};