|
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
|
|
TranscodePolicy,
|
|
|
|
|
VideoCodec,
|
|
|
|
|
} from 'src/enum';
|
|
|
|
|
import { WithoutProperty } from 'src/repositories/asset.repository';
|
|
|
|
|
import { MediaService } from 'src/services/media.service';
|
|
|
|
|
import { JobCounts, RawImageInfo } from 'src/types';
|
|
|
|
|
import { assetStub } from 'test/fixtures/asset.stub';
|
|
|
|
@@ -841,16 +840,12 @@ describe(MediaService.name, () => {
|
|
|
|
|
|
|
|
|
|
describe('handleQueueVideoConversion', () => {
|
|
|
|
|
it('should queue all video assets', async () => {
|
|
|
|
|
mocks.asset.getAll.mockResolvedValue({
|
|
|
|
|
items: [assetStub.video],
|
|
|
|
|
hasNextPage: false,
|
|
|
|
|
});
|
|
|
|
|
mocks.assetJob.streamForVideoConversion.mockReturnValue(makeStream([assetStub.video]));
|
|
|
|
|
mocks.person.getAll.mockReturnValue(makeStream());
|
|
|
|
|
|
|
|
|
|
await sut.handleQueueVideoConversion({ force: true });
|
|
|
|
|
|
|
|
|
|
expect(mocks.asset.getAll).toHaveBeenCalledWith({ skip: 0, take: 1000 }, { type: AssetType.VIDEO });
|
|
|
|
|
expect(mocks.asset.getWithout).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.assetJob.streamForVideoConversion).toHaveBeenCalledWith(true);
|
|
|
|
|
expect(mocks.job.queueAll).toHaveBeenCalledWith([
|
|
|
|
|
{
|
|
|
|
|
name: JobName.VIDEO_CONVERSION,
|
|
|
|
@@ -860,15 +855,11 @@ describe(MediaService.name, () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should queue all video assets without encoded videos', async () => {
|
|
|
|
|
mocks.asset.getWithout.mockResolvedValue({
|
|
|
|
|
items: [assetStub.video],
|
|
|
|
|
hasNextPage: false,
|
|
|
|
|
});
|
|
|
|
|
mocks.assetJob.streamForVideoConversion.mockReturnValue(makeStream([assetStub.video]));
|
|
|
|
|
|
|
|
|
|
await sut.handleQueueVideoConversion({});
|
|
|
|
|
|
|
|
|
|
expect(mocks.asset.getAll).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.asset.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.ENCODED_VIDEO);
|
|
|
|
|
expect(mocks.assetJob.streamForVideoConversion).toHaveBeenCalledWith(void 0);
|
|
|
|
|
expect(mocks.job.queueAll).toHaveBeenCalledWith([
|
|
|
|
|
{
|
|
|
|
|
name: JobName.VIDEO_CONVERSION,
|
|
|
|
@@ -880,26 +871,18 @@ describe(MediaService.name, () => {
|
|
|
|
|
|
|
|
|
|
describe('handleVideoConversion', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.assetJob.getForVideoConversion.mockResolvedValue(assetStub.video);
|
|
|
|
|
sut.videoInterfaces = { dri: ['renderD128'], mali: true };
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should skip transcoding if asset not found', async () => {
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([]);
|
|
|
|
|
mocks.assetJob.getForVideoConversion.mockResolvedValue(void 0);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.probe).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should skip transcoding if non-video asset', async () => {
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.image]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.image.id });
|
|
|
|
|
expect(mocks.media.probe).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should transcode the longest stream', async () => {
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.logger.isLevelEnabled.mockReturnValue(false);
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.multipleVideoStreams);
|
|
|
|
|
|
|
|
|
@@ -921,14 +904,12 @@ describe(MediaService.name, () => {
|
|
|
|
|
|
|
|
|
|
it('should skip a video without any streams', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.noVideoStreams);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should skip a video without any height', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.noHeight);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -936,7 +917,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should throw an error if an unknown transcode policy is configured', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.noAudioStreams);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: 'foo' } } as never as SystemConfig);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
@@ -947,7 +927,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { transcode: TranscodePolicy.ALL, accel: TranscodeHWAccel.DISABLED },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.media.transcode.mockRejectedValue(new Error('Error transcoding video'));
|
|
|
|
|
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED);
|
|
|
|
@@ -957,7 +936,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should transcode when set to all', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.multipleVideoStreams);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.ALL } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1035,7 +1013,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should scale horizontally when video is horizontal', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1051,7 +1028,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should scale vertically when video is vertical', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVertical2160p);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1069,7 +1045,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { transcode: TranscodePolicy.ALL, targetResolution: 'original' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1087,7 +1062,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { transcode: TranscodePolicy.ALL, targetResolution: 'original' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1105,7 +1079,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { targetVideoCodec: VideoCodec.HEVC, acceptedAudioCodecs: [AudioCodec.AAC] },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1127,7 +1100,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
acceptedAudioCodecs: [AudioCodec.AAC],
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1149,7 +1121,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
acceptedAudioCodecs: [AudioCodec.AAC],
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1165,7 +1136,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should copy audio stream when audio matches target', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.audioStreamAac);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1180,7 +1150,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
|
|
|
|
|
it('should remux when input is not an accepted container', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamAvi);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1204,7 +1173,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should not transcode if transcoding is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1212,7 +1180,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should not remux when input is not an accepted container and transcoding is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1220,7 +1187,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should not transcode if target codec is invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: 'invalid' as any } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1229,7 +1195,7 @@ describe(MediaService.name, () => {
|
|
|
|
|
const asset = assetStub.hasEncodedVideo;
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([asset]);
|
|
|
|
|
mocks.assetJob.getForVideoConversion.mockResolvedValue(asset);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: asset.id });
|
|
|
|
|
|
|
|
|
@@ -1243,7 +1209,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set max bitrate if above 0', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { maxBitrate: '4500k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1259,7 +1224,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should default max bitrate to kbps if no unit is provided', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { maxBitrate: '4500' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1275,7 +1239,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should transcode in two passes for h264/h265 when enabled and max bitrate is above 0', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { twoPass: true, maxBitrate: '4500k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1291,7 +1254,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should fallback to one pass for h264/h265 if two-pass is enabled but no max bitrate is set', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { twoPass: true } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1313,7 +1275,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
targetVideoCodec: VideoCodec.VP9,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1335,7 +1296,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
targetVideoCodec: VideoCodec.VP9,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1351,7 +1311,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should configure preset for vp9', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.VP9, preset: 'slow' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1367,7 +1326,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should not configure preset for vp9 if invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { preset: 'invalid', targetVideoCodec: VideoCodec.VP9 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1383,7 +1341,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should configure threads if above 0', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.VP9, threads: 2 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1399,7 +1356,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should disable thread pooling for h264 if thread limit is 1', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 1 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1415,7 +1371,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should omit thread flags for h264 if thread limit is at or below 0', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 0 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1431,7 +1386,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should disable thread pooling for hevc if thread limit is 1', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 1, targetVideoCodec: VideoCodec.HEVC } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1447,7 +1401,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should omit thread flags for hevc if thread limit is at or below 0', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 0, targetVideoCodec: VideoCodec.HEVC } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1463,7 +1416,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should use av1 if specified', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1489,7 +1441,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should map `veryslow` preset to 4 for av1', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, preset: 'veryslow' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1505,7 +1456,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set max bitrate for av1 if specified', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, maxBitrate: '2M' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1521,7 +1471,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set threads for av1 if specified', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, threads: 4 } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1539,7 +1488,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { targetVideoCodec: VideoCodec.AV1, threads: 4, maxBitrate: '2M' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1561,7 +1509,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
targetResolution: '1080p',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1571,7 +1518,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.NVENC, targetVideoCodec: VideoCodec.VP9 },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1579,7 +1525,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should fail if hwaccel option is invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: 'invalid' as any } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -1587,7 +1532,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set options for nvenc', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1625,7 +1569,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
twoPass: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1641,7 +1584,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set vbr options for nvenc when max bitrate is enabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, maxBitrate: '10000k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1657,7 +1599,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set cq options for nvenc when max bitrate is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, maxBitrate: '10000k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1673,7 +1614,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should omit preset for nvenc if invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, preset: 'invalid' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1689,7 +1629,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should ignore two pass for nvenc if max bitrate is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1707,7 +1646,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1730,7 +1668,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1752,7 +1689,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1768,7 +1704,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set options for qsv', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, maxBitrate: '10000k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1809,7 +1744,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
preferredHwDevice: '/dev/dri/renderD128',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1828,7 +1762,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should omit preset for qsv if invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, preset: 'invalid' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1849,7 +1782,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.QSV, targetVideoCodec: VideoCodec.VP9 },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1869,7 +1801,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
sut.videoInterfaces = { dri: [], mali: false };
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError();
|
|
|
|
|
|
|
|
|
@@ -1880,7 +1811,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false };
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -1901,7 +1831,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -1928,7 +1857,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -1958,7 +1886,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true, preferredHwDevice: 'renderD129' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
@@ -1977,7 +1904,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -2000,7 +1926,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set options for vaapi', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2031,7 +1956,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set vbr options for vaapi when max bitrate is enabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, maxBitrate: '10000k' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2056,7 +1980,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set cq options for vaapi when max bitrate is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2081,7 +2004,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should omit preset for vaapi if invalid', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, preset: 'invalid' } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2101,7 +2023,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false };
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2123,7 +2044,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.VAAPI, preferredHwDevice: '/dev/dri/renderD128' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2144,7 +2064,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -2170,7 +2089,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -2194,7 +2112,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -2215,7 +2132,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true, preferredHwDevice: 'renderD129' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
@@ -2232,7 +2148,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should fallback to hw encoding and sw decoding if hw transcoding fails and hw decoding is enabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.media.transcode.mockRejectedValueOnce(new Error('error'));
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledTimes(2);
|
|
|
|
@@ -2253,7 +2168,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should fallback to sw decoding if fallback to sw decoding + hw encoding fails', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.media.transcode.mockRejectedValueOnce(new Error('error'));
|
|
|
|
|
mocks.media.transcode.mockRejectedValueOnce(new Error('error'));
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
@@ -2272,7 +2186,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should fallback to sw transcoding if hw transcoding fails and hw decoding is disabled', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
mocks.media.transcode.mockRejectedValueOnce(new Error('error'));
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledTimes(2);
|
|
|
|
@@ -2291,7 +2204,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
sut.videoInterfaces = { dri: [], mali: true };
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError();
|
|
|
|
|
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
@@ -2299,7 +2211,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should set options for rkmpp', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2340,7 +2251,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
targetVideoCodec: VideoCodec.HEVC,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2358,7 +2268,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2376,7 +2285,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2399,7 +2307,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2419,7 +2326,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: false, crf: 30, maxBitrate: '0' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2442,7 +2348,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
|
|
|
ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' },
|
|
|
|
|
});
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2462,7 +2367,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should tonemap when policy is required and video is hdr', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamHDR);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2482,7 +2386,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should tonemap when policy is optimal and video is hdr', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStreamHDR);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2502,7 +2405,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should transcode when policy is required and video is not yuv420p', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream10Bit);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2518,7 +2420,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should convert to yuv420p when scaling without tone-mapping', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream4K10Bit);
|
|
|
|
|
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } });
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
expect(mocks.media.transcode).toHaveBeenCalledWith(
|
|
|
|
|
'/original/path.ext',
|
|
|
|
@@ -2534,7 +2435,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should count frames for progress when log level is debug', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer);
|
|
|
|
|
mocks.logger.isLevelEnabled.mockReturnValue(true);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
@@ -2557,7 +2457,6 @@ describe(MediaService.name, () => {
|
|
|
|
|
it('should not count frames for progress when log level is not debug', async () => {
|
|
|
|
|
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
|
|
|
|
mocks.logger.isLevelEnabled.mockReturnValue(false);
|
|
|
|
|
mocks.asset.getByIds.mockResolvedValue([assetStub.video]);
|
|
|
|
|
await sut.handleVideoConversion({ id: assetStub.video.id });
|
|
|
|
|
|
|
|
|
|
expect(mocks.media.probe).toHaveBeenCalledWith(assetStub.video.originalPath, { countFrames: false });
|
|
|
|
|