mirror of
https://github.com/immich-app/immich.git
synced 2025-09-29 15:31:13 -04:00
override reserved metadata
This commit is contained in:
parent
38226fd240
commit
9e70f14a8a
@ -203,6 +203,9 @@ export class MediaRepository {
|
|||||||
isHDR: stream.color_transfer === 'smpte2084' || stream.color_transfer === 'arib-std-b67',
|
isHDR: stream.color_transfer === 'smpte2084' || stream.color_transfer === 'arib-std-b67',
|
||||||
bitrate: this.parseInt(stream.bit_rate),
|
bitrate: this.parseInt(stream.bit_rate),
|
||||||
pixelFormat: stream.pix_fmt || 'yuv420p',
|
pixelFormat: stream.pix_fmt || 'yuv420p',
|
||||||
|
colorPrimaries: stream.color_primaries,
|
||||||
|
colorSpace: stream.color_space,
|
||||||
|
colorTransfer: stream.color_transfer,
|
||||||
})),
|
})),
|
||||||
audioStreams: results.streams
|
audioStreams: results.streams
|
||||||
.filter((stream) => stream.codec_type === 'audio')
|
.filter((stream) => stream.codec_type === 'audio')
|
||||||
|
@ -445,6 +445,7 @@ describe(MediaService.name, () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not skip intra frames for MTS file', async () => {
|
it('should not skip intra frames for MTS file', async () => {
|
||||||
mocks.media.probe.mockResolvedValue(probeStub.videoStreamMTS);
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamMTS);
|
||||||
mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.video);
|
mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.video);
|
||||||
@ -462,6 +463,25 @@ describe(MediaService.name, () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should override reserved color metadata', async () => {
|
||||||
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamReserved);
|
||||||
|
mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.video);
|
||||||
|
await sut.handleGenerateThumbnails({ id: assetStub.video.id });
|
||||||
|
|
||||||
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
||||||
|
'/original/path.ext',
|
||||||
|
expect.any(String),
|
||||||
|
expect.objectContaining({
|
||||||
|
inputOptions: expect.arrayContaining([
|
||||||
|
'-bsf:v hevc_metadata=colour_primaries=1:matrix_coefficients=1:transfer_characteristics=1',
|
||||||
|
]),
|
||||||
|
outputOptions: expect.any(Array),
|
||||||
|
progress: expect.any(Object),
|
||||||
|
twoPass: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should use scaling divisible by 2 even when using quick sync', async () => {
|
it('should use scaling divisible by 2 even when using quick sync', async () => {
|
||||||
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
||||||
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHardwareAcceleration.Qsv } });
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHardwareAcceleration.Qsv } });
|
||||||
|
@ -88,6 +88,9 @@ export interface VideoStreamInfo {
|
|||||||
isHDR: boolean;
|
isHDR: boolean;
|
||||||
bitrate: number;
|
bitrate: number;
|
||||||
pixelFormat: string;
|
pixelFormat: string;
|
||||||
|
colorPrimaries?: string;
|
||||||
|
colorSpace?: string;
|
||||||
|
colorTransfer?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AudioStreamInfo {
|
export interface AudioStreamInfo {
|
||||||
|
@ -392,9 +392,30 @@ export class ThumbnailConfig extends BaseConfig {
|
|||||||
|
|
||||||
getBaseInputOptions(videoStream: VideoStreamInfo, format?: VideoFormat): string[] {
|
getBaseInputOptions(videoStream: VideoStreamInfo, format?: VideoFormat): string[] {
|
||||||
// skip_frame nointra skips all frames for some MPEG-TS files. Look at ffmpeg tickets 7950 and 7895 for more details.
|
// skip_frame nointra skips all frames for some MPEG-TS files. Look at ffmpeg tickets 7950 and 7895 for more details.
|
||||||
return format?.formatName === 'mpegts'
|
const options =
|
||||||
|
format?.formatName === 'mpegts'
|
||||||
? ['-sws_flags accurate_rnd+full_chroma_int']
|
? ['-sws_flags accurate_rnd+full_chroma_int']
|
||||||
: ['-skip_frame nointra', '-sws_flags accurate_rnd+full_chroma_int'];
|
: ['-skip_frame nointra', '-sws_flags accurate_rnd+full_chroma_int'];
|
||||||
|
|
||||||
|
const metadataOverrides = [];
|
||||||
|
if (videoStream.colorPrimaries === 'reserved') {
|
||||||
|
metadataOverrides.push('colour_primaries=1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoStream.colorSpace === 'reserved') {
|
||||||
|
metadataOverrides.push('matrix_coefficients=1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoStream.colorTransfer === 'reserved') {
|
||||||
|
metadataOverrides.push('transfer_characteristics=1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadataOverrides.length > 0) {
|
||||||
|
// workaround for https://fftrac-bg.ffmpeg.org/ticket/11020
|
||||||
|
options.push(`-bsf:v ${videoStream.codecName}_metadata=${metadataOverrides.join(':')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBaseOutputOptions() {
|
getBaseOutputOptions() {
|
||||||
|
11
server/test/fixtures/media.stub.ts
vendored
11
server/test/fixtures/media.stub.ts
vendored
@ -261,4 +261,15 @@ export const probeStub = {
|
|||||||
bitrate: 0,
|
bitrate: 0,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
videoStreamReserved: Object.freeze<VideoInfo>({
|
||||||
|
...probeStubDefault,
|
||||||
|
videoStreams: [
|
||||||
|
{
|
||||||
|
...probeStubDefaultVideoStream[0],
|
||||||
|
colorPrimaries: 'reserved',
|
||||||
|
colorSpace: 'reserved',
|
||||||
|
colorTransfer: 'reserved',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user