UNPKG

@eleven-am/transcoder

Version:

High-performance HLS transcoding library with hardware acceleration, intelligent client management, and distributed processing support for Node.js

332 lines 11.5 kB
import { Result, TaskEither } from '@eleven-am/fp'; import { HardwareAccelerationDetector } from './hardwareAccelerationDetector'; import { JobProcessor } from './jobProcessor'; import { MediaSource } from './mediaSource'; import { MetadataService } from './metadataService'; import { QualityService } from './qualityService'; import { AudioQuality, AudioQualityEnum, HardwareAccelerationConfig, MediaMetadata, SegmentStream, StreamConfig, StreamMetricsEvent, StreamType, SubtitleInfo, TranscodeJob, VideoQuality, VideoQualityEnum } from './types'; import { ExtendedEventEmitter } from './utils'; interface StreamEventMap { 'transcode:complete': TranscodeJob; 'transcode:queued': TranscodeJob; 'transcode:error': { job: TranscodeJob; error: Error; }; 'transcode:start': TranscodeJob; 'transcode:fallback': { job: TranscodeJob; from: string; to: string; }; 'stream:metrics': StreamMetricsEvent; 'dispose': { id: string; }; } interface DetailedVideoQuality extends VideoQuality { width: number; height: number; } export declare class Stream extends ExtendedEventEmitter<StreamEventMap> { private readonly quality; private readonly type; private readonly source; private readonly streamIndex; private readonly metadata; private readonly maxSegmentBatchSize; private readonly qualityService; private readonly hwDetector; private readonly optimisedAccel; private readonly jobProcessor; private static readonly DEFAULT_CONFIG; private readonly videoQuality; private readonly audioQuality; private readonly segments; private readonly jobRange; private readonly config; private readonly metrics; private readonly cachedHwOptions; private readonly segmentRetries; private timer; private hasFallenBackToSoftware; private readonly streamCreatedAt; private lastActivityAt; private metricsTimer; private constructor(); /** * Create a new stream * @param quality - The quality of the stream * @param type - The type of the stream (audio or video) * @param streamIndex - The index of the stream * @param source - The media source * @param maxSegmentBatchSize - The maximum number of segments to process at once * @param qualityService - The quality service * @param metadataService - The metadata service * @param hwDetector - The hardware acceleration detector * @param hwAccel - The hardware acceleration configuration * @param config - The stream configuration * @param jobProcessor - The job processor */ static create(quality: string, type: StreamType, streamIndex: number, source: MediaSource, maxSegmentBatchSize: number, qualityService: QualityService, metadataService: MetadataService, hwDetector: HardwareAccelerationDetector, hwAccel: HardwareAccelerationConfig | null, config: Partial<StreamConfig>, jobProcessor: JobProcessor): TaskEither<Stream>; /** * Get the stream ID * @param fileId - The file ID * @param type - The type of the stream (audio or video) * @param quality - The quality of the stream * @param streamIndex - The index of the stream */ static getStreamId(fileId: string, type: StreamType, quality: string, streamIndex: number): string; /** * Extract subtitle from a media source and convert to WebVTT * @param mediaSource - The media source * @param streamIndex - The index of the subtitle stream */ static getVTTSubtitle(mediaSource: MediaSource, streamIndex: number): Promise<NodeJS.ReadableStream>; /** * Get all convertible subtitle streams from media metadata * @param metadata - The media metadata */ static getConvertibleSubtitles(metadata: MediaMetadata): SubtitleInfo[]; /** * Check if a subtitle stream can be converted to VTT * @param subtitleStream - The subtitle stream */ private static canConvertToVtt; /** * Run FFMPEG command * @param outputOptions - The output options to feed to the Ffmpeg * @param inputPath - The input path to the file to perform the command on */ private static runFFMPEGCommand; /** * Create a screenshot from a media source at a specific timestamp * @param timestamp - The timestamp of the screenshot to be created */ generateScreenshot(timestamp: number): Promise<NodeJS.ReadableStream>; /** * Get the file ID */ getFileId(): string; /** * Builds the transcode command for the stream * @param segmentIndex - The index of the segment * @param priority - The priority of the segment */ buildTranscodeCommand(segmentIndex: number, priority: number): TaskEither<void>; /** * Get the segment stream for a specific segment * @param segmentIndex - The index of the segment * @param priority - The priority of the segment */ getSegmentStream(segmentIndex: number, priority: number): TaskEither<SegmentStream>; /** * Get the stream ID */ getStreamId(): string; /** * Creates a new playlist for the stream */ getPlaylist(): string; /** * Builds the video quality for the stream * @param quality - The video quality to build * @param index - The index of the video stream */ buildVideoQuality(quality: VideoQualityEnum, index?: number): DetailedVideoQuality; /** * Builds the audio quality for the stream * @param quality - The audio quality to build * @param index - The index of the audio stream */ buildAudioQuality(quality: AudioQualityEnum, index?: number): AudioQuality; /** * Dispose of the stream */ dispose(): Promise<Result<void>>; /** * Generate and emit comprehensive stream metrics */ private emitMetrics; /** * Calculate current segment states */ private calculateSegmentStates; /** * Initialize the stream */ private initialise; /** * Start a timer to periodically emit metrics */ private startPeriodicMetrics; /** * Get dynamic batch size based on hardware acceleration */ private getDynamicBatchSize; /** * Get cached hardware acceleration options * Uses optimisedAccel unless we've fallen back to software * @param width - Video width * @param height - Video height * @param codec - Codec type */ private getCachedHardwareOptions; /** * Check if an error is related to hardware acceleration * @param err - The error to check */ private isHardwareAccelerationError; /** * Fallback to software encoding while preserving the original optimized config */ private fallbackToSoftwareEncoding; /** * Get the segment for this stream (Audio) * @param segment - The segment to process * @param priority - The priority of the segment */ private buildAudioTranscodeOptions; /** * Build the FFMPEG command for video transcoding * @param segment - The segment to process * @param priority - The priority of the segment */ private buildVideoTranscodeOptions; /** * Build the segments for this stream */ private buildSegments; /** * Prefetch upcoming segments to improve performance * @param currentIndex - The current segment index being processed * @param priority - The priority of the current segment */ private prefetchSegments; /** * Check the status of the segments */ private checkSegmentsStatus; /** * Check if the segment file exists * @param segment - The segment to check */ private checkSegmentFileStatus; /** * Intelligently filter and prepare segments for processing * Only processes segments that actually need work, respects ongoing jobs * @param initialSegment - The segment to start processing from */ private filterAndPrepareSegments; /** * Optimize batch of segments for efficient FFmpeg processing * Groups consecutive segments to minimize FFmpeg invocations */ private optimizeBatchForProcessing; /** * Generate FFMPEG transcoding arguments for processing segments */ private getTranscodeArgs; /** * Build the FFMPEG command for transcoding */ private buildFFMPEGCommand; /** * Execute the actual Ffmpeg transcoding command */ private executeTranscodeCommand; /** * Setup and run the Ffmpeg command with proper event handling */ private setupAndRunCommand; /** * Create the Ffmpeg command with options */ private createFfmpegCommand; /** * Create a transcode job */ private createTranscodeJob; /** * Create a job range */ private createJobRange; /** * Set up comprehensive event handlers for the Ffmpeg command * @param command - The Ffmpeg command * @param job - The transcode job * @param jobRange - The job range * @param segments - The segments being processed * @param resolve - Resolve function * @param reject - Reject function */ private setupCommandEventHandlers; /** * Handle segment progress updates * @param segmentIndex - The index of the segment */ private handleSegmentProgress; /** * Handle transcoding errors with potential hardware acceleration fallback * @param err - The error that occurred * @param job - The job that was processing * @param jobRange - The job range that was processing * @param segments - The segments that were being processed * @param lastIndex - The last index processed * @param disposeHandler - The disposed handler to call */ private handleTranscodeError; /** * Check if we should retry with fallback * @param err - The error to check * @param segmentIndex - The index of the segment */ private shouldRetryWithFallback; /** * Retry transcoding with software fallback * @param segment - The segment to retry * @param originalJob - The original job * @param lock - The distributed lock (if any) * @param resolve - Resolve function * @param reject - Reject function */ private retryWithFallback; /** * Update metrics on successful completion * @param segmentCount - Number of segments processed * @param processingTime - Time taken to process segments */ private updateMetricsOnSuccess; /** * Calculate the closest multiple of x to n */ private closestMultiple; /** * Load the quality of the stream */ private loadQuality; /** * Debounce the dispose method */ private debounceDispose; /** * Calculate distance from current encoders to a segment * @param segmentIndex - The index of the segment */ private getMinEncoderDistance; /** * Check if a segment is already scheduled for processing * @param segmentIndex - The index of the segment */ private isSegmentScheduled; /** * Check if hardware acceleration is being used */ private isUsingHardwareAcceleration; /** * Get the current acceleration method */ private getCurrentAccelerationMethod; } export {}; //# sourceMappingURL=stream.d.ts.map