@eleven-am/transcoder
Version:
High-performance HLS transcoding library with hardware acceleration, intelligent client management, and distributed processing support for Node.js
211 lines • 7.83 kB
JavaScript
"use strict";
/*
* @eleven-am/transcoder
* Copyright (C) 2025 Roy OSSAI
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.QualityService = void 0;
const types_1 = require("./types");
const vQualities = [
types_1.VideoQualityEnum.P240,
types_1.VideoQualityEnum.P360,
types_1.VideoQualityEnum.P480,
types_1.VideoQualityEnum.P720,
types_1.VideoQualityEnum.P1080,
types_1.VideoQualityEnum.P1440,
types_1.VideoQualityEnum.P4K,
types_1.VideoQualityEnum.P8K,
];
const aQualities = [
types_1.AudioQualityEnum.AAC,
types_1.AudioQualityEnum.ORIGINAL,
];
class QualityService {
constructor(videoQualities = vQualities, audioQualities = aQualities) {
this.videoQualities = videoQualities;
this.audioQualities = audioQualities;
this.videoQualityMap = {
[types_1.VideoQualityEnum.P240]: {
value: types_1.VideoQualityEnum.P240,
averageBitrate: 400_000,
maxBitrate: 700_000,
height: 240,
},
[types_1.VideoQualityEnum.P360]: {
value: types_1.VideoQualityEnum.P360,
averageBitrate: 800_000,
maxBitrate: 1_400_000,
height: 360,
},
[types_1.VideoQualityEnum.P480]: {
value: types_1.VideoQualityEnum.P480,
averageBitrate: 1_200_000,
maxBitrate: 2_100_000,
height: 480,
},
[types_1.VideoQualityEnum.P720]: {
value: types_1.VideoQualityEnum.P720,
averageBitrate: 2_400_000,
maxBitrate: 4_000_000,
height: 720,
},
[types_1.VideoQualityEnum.P1080]: {
value: types_1.VideoQualityEnum.P1080,
averageBitrate: 4_800_000,
maxBitrate: 8_000_000,
height: 1080,
},
[types_1.VideoQualityEnum.P1440]: {
value: types_1.VideoQualityEnum.P1440,
averageBitrate: 9_600_000,
maxBitrate: 12_000_000,
height: 1440,
},
[types_1.VideoQualityEnum.P4K]: {
value: types_1.VideoQualityEnum.P4K,
averageBitrate: 16_000_000,
maxBitrate: 28_000_000,
height: 2160,
},
[types_1.VideoQualityEnum.P8K]: {
value: types_1.VideoQualityEnum.P8K,
averageBitrate: 28_000_000,
maxBitrate: 40_000_000,
height: 4320,
},
[types_1.VideoQualityEnum.ORIGINAL]: { value: types_1.VideoQualityEnum.ORIGINAL,
averageBitrate: -1,
maxBitrate: -1,
height: -1 },
};
this.audioQualityMap = {
[types_1.AudioQualityEnum.AAC]: { value: types_1.AudioQualityEnum.AAC,
averageBitrate: 128_000,
maxBitrate: 192_000 },
[types_1.AudioQualityEnum.ORIGINAL]: { value: types_1.AudioQualityEnum.ORIGINAL,
averageBitrate: -1,
maxBitrate: -1 },
};
}
/**
* Determine the appropriate quality for a video
* @param video The video to determine quality for
* @returns The appropriate quality level
*/
determineVideoQuality(video) {
for (const qualityValue of this.videoQualities) {
const quality = this.videoQualityMap[qualityValue];
if (quality.height >= video.height) {
return quality;
}
}
return this.videoQualityMap[this.videoQualities[0]];
}
/**
* Determine the appropriate audio quality for a video
* @param audio The video to determine audio quality for
* @returns The appropriate audio quality level
*/
determineAudioQuality(audio) {
for (const qualityValue of this.audioQualities) {
const quality = this.audioQualityMap[qualityValue];
if (quality.averageBitrate >= audio.bitrate) {
return quality;
}
}
return this.audioQualityMap[this.audioQualities[0]];
}
/**
* Parse a quality string into a Quality object
* @param qualityStr The quality string to parse
* @throws Error if the quality string is invalid
*/
parseVideoQuality(qualityStr) {
const quality = this.videoQualityMap[qualityStr];
if (!quality) {
throw new Error(`Invalid quality: ${qualityStr}`);
}
return quality;
}
/**
* Parse a quality string into an AudioQuality object
* @param qualityStr The quality string to parse
* @throws Error if the quality string is invalid
*/
parseAudioQuality(qualityStr) {
const quality = this.audioQualityMap[qualityStr];
if (!quality) {
throw new Error(`Invalid quality: ${qualityStr}`);
}
return quality;
}
/**
* Gets the available qualities for a video
* @param video The video to get qualities for
* @returns An array of available qualities for the video
*/
getVideoQualities(video) {
const determinedQuality = this.determineVideoQuality(video);
const result = [];
for (const qualityValue of this.videoQualities) {
const quality = this.videoQualityMap[qualityValue];
result.push(quality);
if (quality.value === determinedQuality.value) {
break;
}
}
return result;
}
/**
* Get the non-transcode video qualities
*/
getNonTranscodeVideoQualities() {
return this.videoQualityMap[types_1.VideoQualityEnum.ORIGINAL];
}
/**
* Builds a valid audio quality object based on the provided quality and audio info
* @param quality The desired audio quality
* @param audioInfo The audio info object containing bitrate information
*/
buildValidAudioQuality(quality, audioInfo) {
if (quality === types_1.AudioQualityEnum.ORIGINAL) {
return {
value: types_1.AudioQualityEnum.ORIGINAL,
averageBitrate: audioInfo.bitrate * 1.2,
maxBitrate: audioInfo.bitrate * 2,
};
}
return this.parseAudioQuality(quality);
}
/**
* Builds a valid video quality object based on the provided quality and video info
* @param quality The desired video quality
* @param videoInfo The video info object containing bitrate and height information
*/
buildValidVideoQuality(quality, videoInfo) {
if (quality === types_1.VideoQualityEnum.ORIGINAL) {
return {
value: types_1.VideoQualityEnum.ORIGINAL,
averageBitrate: videoInfo.bitrate * 1.2,
maxBitrate: videoInfo.bitrate * 2,
height: videoInfo.height,
};
}
return this.parseVideoQuality(quality);
}
}
exports.QualityService = QualityService;
//# sourceMappingURL=qualityService.js.map