mes-engine 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- package/dist/index.js.map +1 -1
- package/docs/README.md +4 -4
- package/examples/full-demo/backend/package-lock.json +1 -1
- package/examples/simple-usage/package-lock.json +1 -4
- package/package.json +1 -6
- package/src/core/VideoEngine.ts +1 -1
- package/src/engines/FFmpegEngine.ts +2 -2
- package/src/index.ts +12 -12
- package/src/processor.ts +5 -5
- package/src/storage/FileSystemStorage.ts +1 -1
- package/src/streaming/StreamManager.ts +1 -1
package/README.md
CHANGED
|
@@ -73,12 +73,11 @@ console.log('Master Playlist:', manifest.hls?.masterPlaylist);
|
|
|
73
73
|
Full documentation is available in the [docs directory](./docs).
|
|
74
74
|
|
|
75
75
|
### Key Topics:
|
|
76
|
-
- [
|
|
77
|
-
- [
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
80
|
-
- [
|
|
81
|
-
- [API Reference](./docs/api.md)
|
|
76
|
+
- [Adaptive Streaming (HLS)](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/HLS.md)
|
|
77
|
+
- [Video Engines](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/engines.md)
|
|
78
|
+
- [Storage Providers](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/storage.md)
|
|
79
|
+
- [Caching Strategies](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/caching.md)
|
|
80
|
+
- [API Reference](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/API.md)
|
|
82
81
|
|
|
83
82
|
## Supported Engines
|
|
84
83
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/core/events.ts","../../src/core/VideoEngine.ts","../../src/engines/FFmpegEngine.ts","../../src/streaming/StreamManager.ts","../../src/engines/GStreamerEngine.ts","../../src/storage/StorageProvider.ts","../../src/storage/FileSystemStorage.ts","../../src/cache/cacheStrategy.ts","../../src/cache/LRU.ts","../../src/cache/internalCache.ts","../../src/cache/ExternalCache.ts","../../src/processor.ts"],"sourcesContent":["// src/core/events.ts\r\n/**\r\n * Options:\r\n * \r\n * - CHUNK_PROCESSED\r\n * - QUALITY_PROCESSED\r\n * - PROCESSING_COMPLETE\r\n * - ERROR\r\n */\r\nexport enum VideoEvent {\r\n CHUNK_PROCESSED = 'chunkProcessed',\r\n QUALITY_PROCESSED = 'qualityProcessed',\r\n PROCESSING_COMPLETE = 'processingComplete',\r\n ERROR = 'error'\r\n}\r\n","// src/core/VideoEngine.ts\r\nimport { EventEmitter } from 'events';\r\nimport { QualityLevel } from './types.js';\r\n\r\n/**\r\n * Base class for video processing engines (e.g., FFmpeg, GStreamer).\r\n */\r\nexport abstract class VideoEngine extends EventEmitter {\r\n /**\r\n * Extracts and transcodes a chunk of video.\r\n * @param inputPath - Path to source video\r\n * @param outputPath - Destination for the chunk\r\n * @param startTime - Start offset in seconds\r\n * @param quality - Target quality level\r\n */\r\n abstract processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void>;\r\n\r\n /**\r\n * Extracts a frame from the video as an image.\r\n * @param inputPath - Path to source video\r\n * @param outputPath - Destination for the image\r\n * @param time - Time offset in seconds\r\n */\r\n abstract extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void>;\r\n\r\n /**\r\n * Gets the total duration of the video.\r\n * @param inputPath - Path to source video\r\n * @returns Promise resolving to duration in seconds\r\n */\r\n abstract getDuration(inputPath: string): Promise<number>;\r\n}","// src/engines/FFmpegEngine.ts\r\nimport { VideoEngine } from '../core/VideoEngine.js';\r\nimport { QualityLevel } from '../core/types.js';\r\nimport { spawn } from 'child_process';\r\nimport fs from 'fs';\r\nimport { dirname } from 'path';\r\n\r\n/**\r\n * FFmpeg implementation of the VideoEngine.\r\n * Requires `ffmpeg` and `ffprobe` to be installed on the system path.\r\n */\r\nexport class FFmpegEngine extends VideoEngine {\r\n /**\r\n * Processes a chunk of video using FFmpeg.\r\n *\r\n * @param inputPath - The path to the input video file.\r\n * @param outputPath - The path where the processed video chunk will be saved.\r\n * @param startTime - The start time (in seconds) of the chunk to process.\r\n * @param quality - The desired quality level for the output video.\r\n * @returns A Promise that resolves when the chunk is processed, or rejects on error.\r\n */\r\n async processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void> {\r\n // Ensure output directory exists\r\n await fs.promises.mkdir(dirname(outputPath), { recursive: true });\r\n\r\n return new Promise((resolve, reject) => {\r\n const args = [\r\n '-i', inputPath,\r\n '-ss', startTime.toString(),\r\n '-t', '10',\r\n // Force dimensions divisible by 2 for H.264 encoding\r\n // The scale filter with -2 rounds to the nearest even number\r\n '-vf', `scale=-2:${quality.height}`,\r\n '-c:v', 'libx264',\r\n '-b:v', quality.bitrate,\r\n '-c:a', 'aac',\r\n '-b:a', '128k',\r\n '-preset', 'fast',\r\n // Use yuv420p for maximum compatibility\r\n '-pix_fmt', 'yuv420p',\r\n '-y',\r\n outputPath\r\n ];\r\n\r\n const ffmpegProcess = spawn('ffmpeg', args);\r\n\r\n let stderr = '';\r\n\r\n ffmpegProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffmpegProcess.on('error', (err) => {\r\n reject(new Error(`Failed to spawn FFmpeg: ${err.message}`));\r\n });\r\n\r\n ffmpegProcess.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n console.error('FFmpeg stderr:', stderr);\r\n reject(new Error(`FFmpeg error: ${code}\\nCommand: ffmpeg ${args.join(' ')}\\nStderr: ${stderr}`));\r\n }\r\n });\r\n });\r\n }\r\n\r\n async extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void> {\r\n // Ensure output directory exists\r\n await fs.promises.mkdir(dirname(outputPath), { recursive: true });\r\n\r\n return new Promise((resolve, reject) => {\r\n const args = [\r\n '-ss', time.toString(),\r\n '-i', inputPath,\r\n '-vframes', '1',\r\n '-q:v', '2',\r\n '-y',\r\n outputPath\r\n ];\r\n\r\n const ffmpegProcess = spawn('ffmpeg', args);\r\n\r\n let stderr = '';\r\n\r\n ffmpegProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffmpegProcess.on('error', (err) => {\r\n reject(new Error(`Failed to spawn FFmpeg for screenshot: ${err.message}`));\r\n });\r\n\r\n ffmpegProcess.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n console.error('FFmpeg screenshot stderr:', stderr);\r\n reject(new Error(`FFmpeg screenshot error: ${code}\\nCommand: ffmpeg ${args.join(' ')}\\nStderr: ${stderr}`));\r\n }\r\n });\r\n });\r\n }\r\n\r\n async getDuration(inputPath: string): Promise<number> {\r\n // Use ffprobe for more reliable duration detection\r\n return new Promise((resolve, reject) => {\r\n const ffprobeProcess = spawn('ffprobe', [\r\n '-v', 'error',\r\n '-show_entries', 'format=duration',\r\n '-of', 'default=noprint_wrappers=1:nokey=1',\r\n inputPath\r\n ]);\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n ffprobeProcess.stdout.on('data', (data) => {\r\n stdout += data.toString();\r\n });\r\n\r\n ffprobeProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffprobeProcess.on('error', (err) => {\r\n // Fallback to buffer parsing if ffprobe not available\r\n console.warn('ffprobe not available, falling back to buffer parsing');\r\n this.getDurationFromBuffer(inputPath)\r\n .then(resolve)\r\n .catch(reject);\r\n });\r\n\r\n ffprobeProcess.on('close', (code) => {\r\n if (code === 0) {\r\n const duration = parseFloat(stdout.trim());\r\n if (!isNaN(duration)) {\r\n resolve(duration);\r\n } else {\r\n reject(new Error('Could not parse duration'));\r\n }\r\n } else {\r\n // Fallback to buffer parsing\r\n this.getDurationFromBuffer(inputPath)\r\n .then(resolve)\r\n .catch(reject);\r\n }\r\n });\r\n });\r\n }\r\n\r\n private async getDurationFromBuffer(inputPath: string): Promise<number> {\r\n const buffer = await fs.promises.readFile(inputPath);\r\n\r\n // Parse MP4 moov atom for duration\r\n if (inputPath.endsWith('.mp4')) {\r\n return this.parseMp4Duration(buffer);\r\n }\r\n\r\n // For other formats, extract from file metadata\r\n return this.parseMediaDuration(buffer);\r\n }\r\n\r\n private parseMp4Duration(buffer: Buffer): number {\r\n const moovStart = buffer.indexOf(Buffer.from('moov'));\r\n if (moovStart === -1) return 0;\r\n\r\n const mvhdStart = buffer.indexOf(Buffer.from('mvhd'), moovStart);\r\n if (mvhdStart === -1) return 0;\r\n\r\n const timeScale = buffer.readUInt32BE(mvhdStart + 12);\r\n const duration = buffer.readUInt32BE(mvhdStart + 16);\r\n\r\n return duration / timeScale;\r\n }\r\n\r\n private parseMediaDuration(buffer: Buffer): number {\r\n // Look for duration metadata in file headers\r\n const durationStr = buffer.toString('utf8', 0, Math.min(1000, buffer.length));\r\n const match = durationStr.match(/duration[\"\\s:]+(\\d+\\.?\\d*)/i);\r\n return match ? parseFloat(match[1]) : 0;\r\n }\r\n}","// src/streaming/StreamManager.ts\r\nimport { Readable } from 'stream';\r\nimport { StorageProvider } from '../storage/StorageProvider.js';\r\n\r\nexport class StreamManager {\r\n private storage: StorageProvider;\r\n\r\n constructor(storage: StorageProvider) {\r\n this.storage = storage;\r\n }\r\n\r\n async createStream(chunkPath: string, range?: { start: number; end: number }): Promise<Readable> {\r\n const data = await this.storage.getChunk(chunkPath);\r\n const stream = new Readable();\r\n\r\n if (range) {\r\n stream.push(data.slice(range.start, range.end + 1));\r\n } else {\r\n stream.push(data);\r\n }\r\n\r\n stream.push(null);\r\n return stream;\r\n }\r\n}","// src/engines/GStreamerEngine.ts\r\nimport { spawn } from 'child_process';\r\nimport { VideoEngine } from '../core/VideoEngine';\r\nimport { QualityLevel } from '../core/types';\r\n\r\nexport class GStreamerEngine extends VideoEngine {\r\n async processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'videoconvert',\r\n '!', 'videoscale',\r\n '!', `video/x-raw,width=-1,height=${quality.height}`,\r\n '!', 'x264enc', `bitrate=${quality.bitrate}`,\r\n '!', 'mp4mux', '!', 'filesink', `location=${outputPath}`\r\n ]);\r\n\r\n gst.on('close', code => {\r\n code === 0 ? resolve() : reject(new Error(`GStreamer error: ${code}`));\r\n });\r\n });\r\n }\r\n\r\n async extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'videoconvert',\r\n '!', 'videorate',\r\n '!', `video/x-raw,framerate=1/1`,\r\n '!', 'videocut', `starting-time=${time * 1000000000}`,\r\n '!', 'jpegenc',\r\n '!', 'filesink', `location=${outputPath}`\r\n ]);\r\n\r\n gst.on('close', code => {\r\n code === 0 ? resolve() : reject(new Error(`GStreamer screenshot error: ${code}`));\r\n });\r\n });\r\n }\r\n\r\n async getDuration(inputPath: string): Promise<number> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'identity', '-debug', 'duration'\r\n ]);\r\n\r\n let output = '';\r\n gst.stdout.on('data', data => output += data);\r\n gst.on('close', code => {\r\n code === 0 ? resolve(parseFloat(output)) : reject(new Error(`GStreamer error: ${code}`));\r\n });\r\n });\r\n }\r\n}\r\n","// src/storage/StorageProvider.ts\r\n/**\r\n * Interface for storage backends (e.g., Local File System, S3, Cloud Storage).\r\n */\r\nexport abstract class StorageProvider {\r\n /** Saves a video chunk to storage */\r\n abstract saveChunk(chunkPath: string, data: Buffer): Promise<void>;\r\n /** Retrieves a video chunk from storage */\r\n abstract getChunk(chunkPath: string): Promise<Buffer>;\r\n /** Deletes a video chunk from storage */\r\n abstract deleteChunk(chunkPath: string): Promise<void>;\r\n}","// src/storage/FileSystemStorage.ts\r\nimport { promises as fs } from 'fs';\r\nimport { StorageProvider } from './StorageProvider.js';\r\n\r\nexport class FileSystemStorage extends StorageProvider {\r\n async saveChunk(chunkPath: string, data: Buffer): Promise<void> {\r\n await fs.writeFile(chunkPath, data);\r\n }\r\n\r\n async getChunk(chunkPath: string): Promise<Buffer> {\r\n return fs.readFile(chunkPath);\r\n }\r\n\r\n async deleteChunk(chunkPath: string): Promise<void> {\r\n await fs.unlink(chunkPath);\r\n }\r\n}","\r\n// cache/CacheStrategy.ts\r\nexport interface CacheOptions {\r\n maxSize: number;\r\n ttl: number;\r\n preloadNextChunk: boolean;\r\n externalCacheUrl?: string;\r\n}\r\n\r\nexport abstract class CacheStrategy {\r\n abstract set(key: string, value: Buffer): Promise<void>;\r\n abstract get(key: string): Promise<Buffer | null>;\r\n abstract preload(key: string): Promise<void>;\r\n abstract clear(): Promise<void>;\r\n}","\r\n// cache/LRU.ts\r\nexport class LRU<T> {\r\n private maxSize: number;\r\n private cache: Map<string, T>;\r\n\r\n constructor(maxSize: number) {\r\n this.maxSize = maxSize;\r\n this.cache = new Map();\r\n }\r\n\r\n set(key: string, value: T): void {\r\n if (this.cache.has(key)) {\r\n this.cache.delete(key);\r\n } else if (this.cache.size >= this.maxSize) {\r\n const oldestKey = this.cache.keys().next().value;\r\n if (oldestKey !== undefined) {\r\n this.cache.delete(oldestKey);\r\n }\r\n }\r\n this.cache.set(key, value);\r\n }\r\n\r\n get(key: string): T | undefined {\r\n if (!this.cache.has(key)) return undefined;\r\n const value = this.cache.get(key)!;\r\n this.cache.delete(key);\r\n this.cache.set(key, value);\r\n return value;\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n}","\r\n// cache/internalCache.ts\r\nimport { LRU } from './LRU';\r\nimport { CacheStrategy, CacheOptions } from './cacheStrategy';\r\nimport { StorageProvider } from '../storage/StorageProvider';\r\n\r\nexport class InternalCache extends CacheStrategy {\r\n private cache: LRU<Buffer>;\r\n private options: CacheOptions;\r\n private storage: StorageProvider;\r\n\r\n constructor(options: CacheOptions, storage: StorageProvider) {\r\n super();\r\n this.options = options;\r\n this.cache = new LRU(options.maxSize);\r\n this.storage = storage;\r\n }\r\n\r\n async set(key: string, value: Buffer): Promise<void> {\r\n this.cache.set(key, value);\r\n }\r\n\r\n async get(key: string): Promise<Buffer | null> {\r\n const cached = this.cache.get(key);\r\n if (cached) return cached;\r\n\r\n try {\r\n const data = await this.storage.getChunk(key);\r\n await this.set(key, data);\r\n return data;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n async preload(key: string): Promise<void> {\r\n if (this.options.preloadNextChunk) {\r\n const nextChunkKey = this.getNextChunkKey(key);\r\n if (!this.cache.get(nextChunkKey)) {\r\n try {\r\n const data = await this.storage.getChunk(nextChunkKey);\r\n await this.set(nextChunkKey, data);\r\n } catch {\r\n // Ignore preload failures\r\n }\r\n }\r\n }\r\n }\r\n\r\n async clear(): Promise<void> {\r\n this.cache.clear();\r\n }\r\n\r\n private getNextChunkKey(currentKey: string): string {\r\n const parts = currentKey.split('_');\r\n const currentChunk = parseInt(parts[parts.length - 1]);\r\n parts[parts.length - 1] = (currentChunk + 1).toString();\r\n return parts.join('_');\r\n }\r\n}","\r\n// cache/ExternalCache.ts\r\nimport fetch from 'node-fetch';\r\nimport { CacheStrategy, CacheOptions } from './cacheStrategy';\r\n\r\nexport class ExternalCache extends CacheStrategy {\r\n private baseUrl: string;\r\n private options: CacheOptions;\r\n\r\n constructor(options: CacheOptions) {\r\n super();\r\n this.options = options;\r\n this.baseUrl = options.externalCacheUrl!;\r\n }\r\n\r\n async set(key: string, value: Buffer): Promise<void> {\r\n await fetch(`${this.baseUrl}/cache/${key}`, {\r\n method: 'POST',\r\n body: value,\r\n headers: {\r\n 'Content-Type': 'application/octet-stream',\r\n 'TTL': this.options.ttl.toString()\r\n }\r\n });\r\n }\r\n\r\n async get(key: string): Promise<Buffer | null> {\r\n const response = await fetch(`${this.baseUrl}/cache/${key}`);\r\n return response.ok ? Buffer.from(await response.arrayBuffer()) : null;\r\n }\r\n\r\n async preload(key: string): Promise<void> {\r\n if (this.options.preloadNextChunk) {\r\n const nextChunkKey = this.getNextChunkKey(key);\r\n await fetch(`${this.baseUrl}/preload/${nextChunkKey}`);\r\n }\r\n }\r\n\r\n async clear(): Promise<void> {\r\n await fetch(`${this.baseUrl}/cache`, { method: 'DELETE' });\r\n }\r\n\r\n private getNextChunkKey(currentKey: string): string {\r\n const parts = currentKey.split('_');\r\n const currentChunk = parseInt(parts[parts.length - 1]);\r\n parts[parts.length - 1] = (currentChunk + 1).toString();\r\n return parts.join('_');\r\n }\r\n}","// src/processor.ts\r\nimport { VideoEngine } from './core/VideoEngine.js';\r\nimport { EventEmitter } from 'events';\r\nimport { StorageProvider } from './storage/StorageProvider.js';\r\nimport { StreamManager } from './streaming/StreamManager.js';\r\nimport { VideoConfig, VideoManifest, VideoChunk, ProcessingOptions } from './core/types.js';\r\nimport { join, dirname } from 'path';\r\nimport { promises as fs } from 'fs';\r\nimport { Readable } from 'stream';\r\nimport { VideoEvent } from './core/events.js';\r\n\r\n/**\r\n * Main orchestrator for video processing.\r\n * Handles chunking, transcoding (via engines), and manifest generation.\r\n */\r\nexport class VideoProcessor extends EventEmitter {\r\n private engine: VideoEngine;\r\n private streamManager: StreamManager;\r\n private config: VideoConfig;\r\n\r\n constructor(\r\n engine: VideoEngine,\r\n storage: StorageProvider,\r\n config: VideoConfig\r\n ) {\r\n super();\r\n this.engine = engine;\r\n this.streamManager = new StreamManager(storage);\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Processes an input video file into multiple quality levels and chunks.\r\n * Generates HLS playlists and a JSON manifest.\r\n * \r\n * @param inputPath - Absolute path to the source video file\r\n * @param options - Optional metadata and processing instructions\r\n * @returns Promise resolving to the generated VideoManifest\r\n * @throws Error if processing fails at any stage\r\n */\r\n async processVideo(\r\n inputPath: string,\r\n options?: ProcessingOptions\r\n ): Promise<VideoManifest> {\r\n const videoId = await this.generateVideoId(inputPath);\r\n const manifest: VideoManifest = {\r\n videoId,\r\n qualities: this.config.defaultQualities,\r\n chunks: [],\r\n metadata: {\r\n title: options?.title,\r\n description: options?.overallDescription,\r\n createdAt: new Date().toISOString()\r\n }\r\n };\r\n\r\n // Create base directory structure\r\n const baseDir = join(this.config.cacheDir, videoId);\r\n const screenshotDir = join(baseDir, 'screenshots');\r\n await fs.mkdir(baseDir, { recursive: true });\r\n await fs.mkdir(screenshotDir, { recursive: true });\r\n\r\n const duration = await this.engine.getDuration(inputPath);\r\n const chunks = Math.ceil(duration / this.config.chunkSize);\r\n\r\n for (const quality of this.config.defaultQualities) {\r\n // Create quality-specific directory\r\n const qualityDir = join(baseDir, `${quality.height}p`);\r\n await fs.mkdir(qualityDir, { recursive: true });\r\n\r\n let m3u8Content = '#EXTM3U\\n#EXT-X-VERSION:3\\n#EXT-X-TARGETDURATION:' + this.config.chunkSize + '\\n#EXT-X-MEDIA-SEQUENCE:0\\n#EXT-X-PLAYLIST-TYPE:VOD\\n';\r\n\r\n for (let i = 0; i < chunks; i++) {\r\n const chunkPath = this.getChunkPath(videoId, quality.height, i);\r\n const screenshotPath = this.getScreenshotPath(videoId, i);\r\n\r\n try {\r\n // Process chunk\r\n await this.engine.processChunk(\r\n inputPath,\r\n chunkPath,\r\n i * this.config.chunkSize,\r\n quality\r\n );\r\n\r\n // Extract screenshot (only once per chunk number, e.g., for the first quality)\r\n if (quality.height === this.config.defaultQualities[0].height) {\r\n await this.engine.extractScreenshot(\r\n inputPath,\r\n screenshotPath,\r\n i * this.config.chunkSize + 1 // 1 second into the chunk\r\n );\r\n }\r\n\r\n const chunk: VideoChunk = {\r\n quality: quality.height,\r\n number: i,\r\n path: chunkPath,\r\n screenshotPath: screenshotPath,\r\n description: options?.descriptions?.[i]\r\n };\r\n\r\n manifest.chunks.push(chunk);\r\n\r\n // Add to M3U8\r\n m3u8Content += `#EXTINF:${this.config.chunkSize}.0,\\nchunk_${i}.mp4\\n`;\r\n\r\n this.emit(VideoEvent.CHUNK_PROCESSED, { quality, chunkNumber: i });\r\n } catch (error) {\r\n this.emit(VideoEvent.ERROR, error);\r\n throw error;\r\n }\r\n }\r\n m3u8Content += '#EXT-X-ENDLIST';\r\n\r\n // Save M3U8 for this quality\r\n const m3u8Path = join(qualityDir, 'playlist.m3u8');\r\n await fs.writeFile(m3u8Path, m3u8Content);\r\n\r\n this.emit(VideoEvent.QUALITY_PROCESSED, quality);\r\n }\r\n\r\n // Generate Master M3U8\r\n if (this.config.defaultQualities.length > 1) {\r\n let masterM3u8 = '#EXTM3U\\n';\r\n for (const quality of this.config.defaultQualities) {\r\n masterM3u8 += `#EXT-X-STREAM-INF:BANDWIDTH=${quality.bitrate.replace('k', '000')},RESOLUTION=-1x${quality.height}\\n${quality.height}p/playlist.m3u8\\n`;\r\n }\r\n const masterPath = join(baseDir, 'master.m3u8');\r\n await fs.writeFile(masterPath, masterM3u8);\r\n }\r\n\r\n // Save JSON Manifest\r\n const manifestPath = join(baseDir, 'manifest.json');\r\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\r\n\r\n this.emit(VideoEvent.PROCESSING_COMPLETE, manifest);\r\n return manifest;\r\n }\r\n\r\n /**\r\n * Creates a readable stream for a specific video chunk.\r\n * Supported for on-demand delivery of processed segments.\r\n * \r\n * @param videoId - ID of the processed video\r\n * @param quality - Target quality (height)\r\n * @param chunkNumber - Sequential index of the chunk\r\n * @param range - Optional byte range for partial content\r\n * @returns Promise resolving to a Readable stream\r\n */\r\n async streamChunk(\r\n videoId: string,\r\n quality: number,\r\n chunkNumber: number,\r\n range?: { start: number; end: number }\r\n ): Promise<Readable> {\r\n const chunkPath = this.getChunkPath(videoId, quality, chunkNumber);\r\n return this.streamManager.createStream(chunkPath, range);\r\n }\r\n\r\n private getChunkPath(videoId: string, quality: number, chunkNumber: number): string {\r\n return join(this.config.cacheDir, videoId, `${quality}p`, `chunk_${chunkNumber}.mp4`);\r\n }\r\n\r\n private getScreenshotPath(videoId: string, chunkNumber: number): string {\r\n return join(this.config.cacheDir, videoId, 'screenshots', `chunk_${chunkNumber}.jpg`);\r\n }\r\n\r\n private async generateVideoId(inputPath: string): Promise<string> {\r\n const stats = await fs.stat(inputPath);\r\n const fileName = inputPath.split(/[\\\\/]/).pop()?.split('.')[0];\r\n return `${fileName}_${Math.floor(stats.mtimeMs)}`;\r\n }\r\n}"],"names":["fs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/core/events.ts","../../src/core/VideoEngine.ts","../../src/engines/FFmpegEngine.ts","../../src/streaming/StreamManager.ts","../../src/engines/GStreamerEngine.ts","../../src/storage/StorageProvider.ts","../../src/storage/FileSystemStorage.ts","../../src/cache/cacheStrategy.ts","../../src/cache/LRU.ts","../../src/cache/internalCache.ts","../../src/cache/ExternalCache.ts","../../src/processor.ts"],"sourcesContent":["// src/core/events.ts\r\n/**\r\n * Options:\r\n * \r\n * - CHUNK_PROCESSED\r\n * - QUALITY_PROCESSED\r\n * - PROCESSING_COMPLETE\r\n * - ERROR\r\n */\r\nexport enum VideoEvent {\r\n CHUNK_PROCESSED = 'chunkProcessed',\r\n QUALITY_PROCESSED = 'qualityProcessed',\r\n PROCESSING_COMPLETE = 'processingComplete',\r\n ERROR = 'error'\r\n}\r\n","// src/core/VideoEngine.ts\r\nimport { EventEmitter } from 'events';\r\nimport { QualityLevel } from './types';\r\n\r\n/**\r\n * Base class for video processing engines (e.g., FFmpeg, GStreamer).\r\n */\r\nexport abstract class VideoEngine extends EventEmitter {\r\n /**\r\n * Extracts and transcodes a chunk of video.\r\n * @param inputPath - Path to source video\r\n * @param outputPath - Destination for the chunk\r\n * @param startTime - Start offset in seconds\r\n * @param quality - Target quality level\r\n */\r\n abstract processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void>;\r\n\r\n /**\r\n * Extracts a frame from the video as an image.\r\n * @param inputPath - Path to source video\r\n * @param outputPath - Destination for the image\r\n * @param time - Time offset in seconds\r\n */\r\n abstract extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void>;\r\n\r\n /**\r\n * Gets the total duration of the video.\r\n * @param inputPath - Path to source video\r\n * @returns Promise resolving to duration in seconds\r\n */\r\n abstract getDuration(inputPath: string): Promise<number>;\r\n}","// src/engines/FFmpegEngine.ts\r\nimport { VideoEngine } from '../core/VideoEngine';\r\nimport { QualityLevel } from '../core/types';\r\nimport { spawn } from 'child_process';\r\nimport fs from 'fs';\r\nimport { dirname } from 'path';\r\n\r\n/**\r\n * FFmpeg implementation of the VideoEngine.\r\n * Requires `ffmpeg` and `ffprobe` to be installed on the system path.\r\n */\r\nexport class FFmpegEngine extends VideoEngine {\r\n /**\r\n * Processes a chunk of video using FFmpeg.\r\n *\r\n * @param inputPath - The path to the input video file.\r\n * @param outputPath - The path where the processed video chunk will be saved.\r\n * @param startTime - The start time (in seconds) of the chunk to process.\r\n * @param quality - The desired quality level for the output video.\r\n * @returns A Promise that resolves when the chunk is processed, or rejects on error.\r\n */\r\n async processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void> {\r\n // Ensure output directory exists\r\n await fs.promises.mkdir(dirname(outputPath), { recursive: true });\r\n\r\n return new Promise((resolve, reject) => {\r\n const args = [\r\n '-i', inputPath,\r\n '-ss', startTime.toString(),\r\n '-t', '10',\r\n // Force dimensions divisible by 2 for H.264 encoding\r\n // The scale filter with -2 rounds to the nearest even number\r\n '-vf', `scale=-2:${quality.height}`,\r\n '-c:v', 'libx264',\r\n '-b:v', quality.bitrate,\r\n '-c:a', 'aac',\r\n '-b:a', '128k',\r\n '-preset', 'fast',\r\n // Use yuv420p for maximum compatibility\r\n '-pix_fmt', 'yuv420p',\r\n '-y',\r\n outputPath\r\n ];\r\n\r\n const ffmpegProcess = spawn('ffmpeg', args);\r\n\r\n let stderr = '';\r\n\r\n ffmpegProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffmpegProcess.on('error', (err) => {\r\n reject(new Error(`Failed to spawn FFmpeg: ${err.message}`));\r\n });\r\n\r\n ffmpegProcess.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n console.error('FFmpeg stderr:', stderr);\r\n reject(new Error(`FFmpeg error: ${code}\\nCommand: ffmpeg ${args.join(' ')}\\nStderr: ${stderr}`));\r\n }\r\n });\r\n });\r\n }\r\n\r\n async extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void> {\r\n // Ensure output directory exists\r\n await fs.promises.mkdir(dirname(outputPath), { recursive: true });\r\n\r\n return new Promise((resolve, reject) => {\r\n const args = [\r\n '-ss', time.toString(),\r\n '-i', inputPath,\r\n '-vframes', '1',\r\n '-q:v', '2',\r\n '-y',\r\n outputPath\r\n ];\r\n\r\n const ffmpegProcess = spawn('ffmpeg', args);\r\n\r\n let stderr = '';\r\n\r\n ffmpegProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffmpegProcess.on('error', (err) => {\r\n reject(new Error(`Failed to spawn FFmpeg for screenshot: ${err.message}`));\r\n });\r\n\r\n ffmpegProcess.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n console.error('FFmpeg screenshot stderr:', stderr);\r\n reject(new Error(`FFmpeg screenshot error: ${code}\\nCommand: ffmpeg ${args.join(' ')}\\nStderr: ${stderr}`));\r\n }\r\n });\r\n });\r\n }\r\n\r\n async getDuration(inputPath: string): Promise<number> {\r\n // Use ffprobe for more reliable duration detection\r\n return new Promise((resolve, reject) => {\r\n const ffprobeProcess = spawn('ffprobe', [\r\n '-v', 'error',\r\n '-show_entries', 'format=duration',\r\n '-of', 'default=noprint_wrappers=1:nokey=1',\r\n inputPath\r\n ]);\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n ffprobeProcess.stdout.on('data', (data) => {\r\n stdout += data.toString();\r\n });\r\n\r\n ffprobeProcess.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n ffprobeProcess.on('error', (err) => {\r\n // Fallback to buffer parsing if ffprobe not available\r\n console.warn('ffprobe not available, falling back to buffer parsing');\r\n this.getDurationFromBuffer(inputPath)\r\n .then(resolve)\r\n .catch(reject);\r\n });\r\n\r\n ffprobeProcess.on('close', (code) => {\r\n if (code === 0) {\r\n const duration = parseFloat(stdout.trim());\r\n if (!isNaN(duration)) {\r\n resolve(duration);\r\n } else {\r\n reject(new Error('Could not parse duration'));\r\n }\r\n } else {\r\n // Fallback to buffer parsing\r\n this.getDurationFromBuffer(inputPath)\r\n .then(resolve)\r\n .catch(reject);\r\n }\r\n });\r\n });\r\n }\r\n\r\n private async getDurationFromBuffer(inputPath: string): Promise<number> {\r\n const buffer = await fs.promises.readFile(inputPath);\r\n\r\n // Parse MP4 moov atom for duration\r\n if (inputPath.endsWith('.mp4')) {\r\n return this.parseMp4Duration(buffer);\r\n }\r\n\r\n // For other formats, extract from file metadata\r\n return this.parseMediaDuration(buffer);\r\n }\r\n\r\n private parseMp4Duration(buffer: Buffer): number {\r\n const moovStart = buffer.indexOf(Buffer.from('moov'));\r\n if (moovStart === -1) return 0;\r\n\r\n const mvhdStart = buffer.indexOf(Buffer.from('mvhd'), moovStart);\r\n if (mvhdStart === -1) return 0;\r\n\r\n const timeScale = buffer.readUInt32BE(mvhdStart + 12);\r\n const duration = buffer.readUInt32BE(mvhdStart + 16);\r\n\r\n return duration / timeScale;\r\n }\r\n\r\n private parseMediaDuration(buffer: Buffer): number {\r\n // Look for duration metadata in file headers\r\n const durationStr = buffer.toString('utf8', 0, Math.min(1000, buffer.length));\r\n const match = durationStr.match(/duration[\"\\s:]+(\\d+\\.?\\d*)/i);\r\n return match ? parseFloat(match[1]) : 0;\r\n }\r\n}","// src/streaming/StreamManager.ts\r\nimport { Readable } from 'stream';\r\nimport { StorageProvider } from '../storage/StorageProvider';\r\n\r\nexport class StreamManager {\r\n private storage: StorageProvider;\r\n\r\n constructor(storage: StorageProvider) {\r\n this.storage = storage;\r\n }\r\n\r\n async createStream(chunkPath: string, range?: { start: number; end: number }): Promise<Readable> {\r\n const data = await this.storage.getChunk(chunkPath);\r\n const stream = new Readable();\r\n\r\n if (range) {\r\n stream.push(data.slice(range.start, range.end + 1));\r\n } else {\r\n stream.push(data);\r\n }\r\n\r\n stream.push(null);\r\n return stream;\r\n }\r\n}","// src/engines/GStreamerEngine.ts\r\nimport { spawn } from 'child_process';\r\nimport { VideoEngine } from '../core/VideoEngine';\r\nimport { QualityLevel } from '../core/types';\r\n\r\nexport class GStreamerEngine extends VideoEngine {\r\n async processChunk(\r\n inputPath: string,\r\n outputPath: string,\r\n startTime: number,\r\n quality: QualityLevel\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'videoconvert',\r\n '!', 'videoscale',\r\n '!', `video/x-raw,width=-1,height=${quality.height}`,\r\n '!', 'x264enc', `bitrate=${quality.bitrate}`,\r\n '!', 'mp4mux', '!', 'filesink', `location=${outputPath}`\r\n ]);\r\n\r\n gst.on('close', code => {\r\n code === 0 ? resolve() : reject(new Error(`GStreamer error: ${code}`));\r\n });\r\n });\r\n }\r\n\r\n async extractScreenshot(\r\n inputPath: string,\r\n outputPath: string,\r\n time: number\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'videoconvert',\r\n '!', 'videorate',\r\n '!', `video/x-raw,framerate=1/1`,\r\n '!', 'videocut', `starting-time=${time * 1000000000}`,\r\n '!', 'jpegenc',\r\n '!', 'filesink', `location=${outputPath}`\r\n ]);\r\n\r\n gst.on('close', code => {\r\n code === 0 ? resolve() : reject(new Error(`GStreamer screenshot error: ${code}`));\r\n });\r\n });\r\n }\r\n\r\n async getDuration(inputPath: string): Promise<number> {\r\n return new Promise((resolve, reject) => {\r\n const gst = spawn('gst-launch-1.0', [\r\n 'filesrc', `location=${inputPath}`,\r\n '!', 'decodebin',\r\n '!', 'identity', '-debug', 'duration'\r\n ]);\r\n\r\n let output = '';\r\n gst.stdout.on('data', data => output += data);\r\n gst.on('close', code => {\r\n code === 0 ? resolve(parseFloat(output)) : reject(new Error(`GStreamer error: ${code}`));\r\n });\r\n });\r\n }\r\n}\r\n","// src/storage/StorageProvider.ts\r\n/**\r\n * Interface for storage backends (e.g., Local File System, S3, Cloud Storage).\r\n */\r\nexport abstract class StorageProvider {\r\n /** Saves a video chunk to storage */\r\n abstract saveChunk(chunkPath: string, data: Buffer): Promise<void>;\r\n /** Retrieves a video chunk from storage */\r\n abstract getChunk(chunkPath: string): Promise<Buffer>;\r\n /** Deletes a video chunk from storage */\r\n abstract deleteChunk(chunkPath: string): Promise<void>;\r\n}","// src/storage/FileSystemStorage.ts\r\nimport { promises as fs } from 'fs';\r\nimport { StorageProvider } from './StorageProvider';\r\n\r\nexport class FileSystemStorage extends StorageProvider {\r\n async saveChunk(chunkPath: string, data: Buffer): Promise<void> {\r\n await fs.writeFile(chunkPath, data);\r\n }\r\n\r\n async getChunk(chunkPath: string): Promise<Buffer> {\r\n return fs.readFile(chunkPath);\r\n }\r\n\r\n async deleteChunk(chunkPath: string): Promise<void> {\r\n await fs.unlink(chunkPath);\r\n }\r\n}","\r\n// cache/CacheStrategy.ts\r\nexport interface CacheOptions {\r\n maxSize: number;\r\n ttl: number;\r\n preloadNextChunk: boolean;\r\n externalCacheUrl?: string;\r\n}\r\n\r\nexport abstract class CacheStrategy {\r\n abstract set(key: string, value: Buffer): Promise<void>;\r\n abstract get(key: string): Promise<Buffer | null>;\r\n abstract preload(key: string): Promise<void>;\r\n abstract clear(): Promise<void>;\r\n}","\r\n// cache/LRU.ts\r\nexport class LRU<T> {\r\n private maxSize: number;\r\n private cache: Map<string, T>;\r\n\r\n constructor(maxSize: number) {\r\n this.maxSize = maxSize;\r\n this.cache = new Map();\r\n }\r\n\r\n set(key: string, value: T): void {\r\n if (this.cache.has(key)) {\r\n this.cache.delete(key);\r\n } else if (this.cache.size >= this.maxSize) {\r\n const oldestKey = this.cache.keys().next().value;\r\n if (oldestKey !== undefined) {\r\n this.cache.delete(oldestKey);\r\n }\r\n }\r\n this.cache.set(key, value);\r\n }\r\n\r\n get(key: string): T | undefined {\r\n if (!this.cache.has(key)) return undefined;\r\n const value = this.cache.get(key)!;\r\n this.cache.delete(key);\r\n this.cache.set(key, value);\r\n return value;\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n}","\r\n// cache/internalCache.ts\r\nimport { LRU } from './LRU';\r\nimport { CacheStrategy, CacheOptions } from './cacheStrategy';\r\nimport { StorageProvider } from '../storage/StorageProvider';\r\n\r\nexport class InternalCache extends CacheStrategy {\r\n private cache: LRU<Buffer>;\r\n private options: CacheOptions;\r\n private storage: StorageProvider;\r\n\r\n constructor(options: CacheOptions, storage: StorageProvider) {\r\n super();\r\n this.options = options;\r\n this.cache = new LRU(options.maxSize);\r\n this.storage = storage;\r\n }\r\n\r\n async set(key: string, value: Buffer): Promise<void> {\r\n this.cache.set(key, value);\r\n }\r\n\r\n async get(key: string): Promise<Buffer | null> {\r\n const cached = this.cache.get(key);\r\n if (cached) return cached;\r\n\r\n try {\r\n const data = await this.storage.getChunk(key);\r\n await this.set(key, data);\r\n return data;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n async preload(key: string): Promise<void> {\r\n if (this.options.preloadNextChunk) {\r\n const nextChunkKey = this.getNextChunkKey(key);\r\n if (!this.cache.get(nextChunkKey)) {\r\n try {\r\n const data = await this.storage.getChunk(nextChunkKey);\r\n await this.set(nextChunkKey, data);\r\n } catch {\r\n // Ignore preload failures\r\n }\r\n }\r\n }\r\n }\r\n\r\n async clear(): Promise<void> {\r\n this.cache.clear();\r\n }\r\n\r\n private getNextChunkKey(currentKey: string): string {\r\n const parts = currentKey.split('_');\r\n const currentChunk = parseInt(parts[parts.length - 1]);\r\n parts[parts.length - 1] = (currentChunk + 1).toString();\r\n return parts.join('_');\r\n }\r\n}","\r\n// cache/ExternalCache.ts\r\nimport fetch from 'node-fetch';\r\nimport { CacheStrategy, CacheOptions } from './cacheStrategy';\r\n\r\nexport class ExternalCache extends CacheStrategy {\r\n private baseUrl: string;\r\n private options: CacheOptions;\r\n\r\n constructor(options: CacheOptions) {\r\n super();\r\n this.options = options;\r\n this.baseUrl = options.externalCacheUrl!;\r\n }\r\n\r\n async set(key: string, value: Buffer): Promise<void> {\r\n await fetch(`${this.baseUrl}/cache/${key}`, {\r\n method: 'POST',\r\n body: value,\r\n headers: {\r\n 'Content-Type': 'application/octet-stream',\r\n 'TTL': this.options.ttl.toString()\r\n }\r\n });\r\n }\r\n\r\n async get(key: string): Promise<Buffer | null> {\r\n const response = await fetch(`${this.baseUrl}/cache/${key}`);\r\n return response.ok ? Buffer.from(await response.arrayBuffer()) : null;\r\n }\r\n\r\n async preload(key: string): Promise<void> {\r\n if (this.options.preloadNextChunk) {\r\n const nextChunkKey = this.getNextChunkKey(key);\r\n await fetch(`${this.baseUrl}/preload/${nextChunkKey}`);\r\n }\r\n }\r\n\r\n async clear(): Promise<void> {\r\n await fetch(`${this.baseUrl}/cache`, { method: 'DELETE' });\r\n }\r\n\r\n private getNextChunkKey(currentKey: string): string {\r\n const parts = currentKey.split('_');\r\n const currentChunk = parseInt(parts[parts.length - 1]);\r\n parts[parts.length - 1] = (currentChunk + 1).toString();\r\n return parts.join('_');\r\n }\r\n}","// src/processor.ts\r\nimport { VideoEngine } from './core/VideoEngine';\r\nimport { EventEmitter } from 'events';\r\nimport { StorageProvider } from './storage/StorageProvider';\r\nimport { StreamManager } from './streaming/StreamManager';\r\nimport { VideoConfig, VideoManifest, VideoChunk, ProcessingOptions } from './core/types';\r\nimport { join, dirname } from 'path';\r\nimport { promises as fs } from 'fs';\r\nimport { Readable } from 'stream';\r\nimport { VideoEvent } from './core/events';\r\n\r\n/**\r\n * Main orchestrator for video processing.\r\n * Handles chunking, transcoding (via engines), and manifest generation.\r\n */\r\nexport class VideoProcessor extends EventEmitter {\r\n private engine: VideoEngine;\r\n private streamManager: StreamManager;\r\n private config: VideoConfig;\r\n\r\n constructor(\r\n engine: VideoEngine,\r\n storage: StorageProvider,\r\n config: VideoConfig\r\n ) {\r\n super();\r\n this.engine = engine;\r\n this.streamManager = new StreamManager(storage);\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Processes an input video file into multiple quality levels and chunks.\r\n * Generates HLS playlists and a JSON manifest.\r\n * \r\n * @param inputPath - Absolute path to the source video file\r\n * @param options - Optional metadata and processing instructions\r\n * @returns Promise resolving to the generated VideoManifest\r\n * @throws Error if processing fails at any stage\r\n */\r\n async processVideo(\r\n inputPath: string,\r\n options?: ProcessingOptions\r\n ): Promise<VideoManifest> {\r\n const videoId = await this.generateVideoId(inputPath);\r\n const manifest: VideoManifest = {\r\n videoId,\r\n qualities: this.config.defaultQualities,\r\n chunks: [],\r\n metadata: {\r\n title: options?.title,\r\n description: options?.overallDescription,\r\n createdAt: new Date().toISOString()\r\n }\r\n };\r\n\r\n // Create base directory structure\r\n const baseDir = join(this.config.cacheDir, videoId);\r\n const screenshotDir = join(baseDir, 'screenshots');\r\n await fs.mkdir(baseDir, { recursive: true });\r\n await fs.mkdir(screenshotDir, { recursive: true });\r\n\r\n const duration = await this.engine.getDuration(inputPath);\r\n const chunks = Math.ceil(duration / this.config.chunkSize);\r\n\r\n for (const quality of this.config.defaultQualities) {\r\n // Create quality-specific directory\r\n const qualityDir = join(baseDir, `${quality.height}p`);\r\n await fs.mkdir(qualityDir, { recursive: true });\r\n\r\n let m3u8Content = '#EXTM3U\\n#EXT-X-VERSION:3\\n#EXT-X-TARGETDURATION:' + this.config.chunkSize + '\\n#EXT-X-MEDIA-SEQUENCE:0\\n#EXT-X-PLAYLIST-TYPE:VOD\\n';\r\n\r\n for (let i = 0; i < chunks; i++) {\r\n const chunkPath = this.getChunkPath(videoId, quality.height, i);\r\n const screenshotPath = this.getScreenshotPath(videoId, i);\r\n\r\n try {\r\n // Process chunk\r\n await this.engine.processChunk(\r\n inputPath,\r\n chunkPath,\r\n i * this.config.chunkSize,\r\n quality\r\n );\r\n\r\n // Extract screenshot (only once per chunk number, e.g., for the first quality)\r\n if (quality.height === this.config.defaultQualities[0].height) {\r\n await this.engine.extractScreenshot(\r\n inputPath,\r\n screenshotPath,\r\n i * this.config.chunkSize + 1 // 1 second into the chunk\r\n );\r\n }\r\n\r\n const chunk: VideoChunk = {\r\n quality: quality.height,\r\n number: i,\r\n path: chunkPath,\r\n screenshotPath: screenshotPath,\r\n description: options?.descriptions?.[i]\r\n };\r\n\r\n manifest.chunks.push(chunk);\r\n\r\n // Add to M3U8\r\n m3u8Content += `#EXTINF:${this.config.chunkSize}.0,\\nchunk_${i}.mp4\\n`;\r\n\r\n this.emit(VideoEvent.CHUNK_PROCESSED, { quality, chunkNumber: i });\r\n } catch (error) {\r\n this.emit(VideoEvent.ERROR, error);\r\n throw error;\r\n }\r\n }\r\n m3u8Content += '#EXT-X-ENDLIST';\r\n\r\n // Save M3U8 for this quality\r\n const m3u8Path = join(qualityDir, 'playlist.m3u8');\r\n await fs.writeFile(m3u8Path, m3u8Content);\r\n\r\n this.emit(VideoEvent.QUALITY_PROCESSED, quality);\r\n }\r\n\r\n // Generate Master M3U8\r\n if (this.config.defaultQualities.length > 1) {\r\n let masterM3u8 = '#EXTM3U\\n';\r\n for (const quality of this.config.defaultQualities) {\r\n masterM3u8 += `#EXT-X-STREAM-INF:BANDWIDTH=${quality.bitrate.replace('k', '000')},RESOLUTION=-1x${quality.height}\\n${quality.height}p/playlist.m3u8\\n`;\r\n }\r\n const masterPath = join(baseDir, 'master.m3u8');\r\n await fs.writeFile(masterPath, masterM3u8);\r\n }\r\n\r\n // Save JSON Manifest\r\n const manifestPath = join(baseDir, 'manifest.json');\r\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\r\n\r\n this.emit(VideoEvent.PROCESSING_COMPLETE, manifest);\r\n return manifest;\r\n }\r\n\r\n /**\r\n * Creates a readable stream for a specific video chunk.\r\n * Supported for on-demand delivery of processed segments.\r\n * \r\n * @param videoId - ID of the processed video\r\n * @param quality - Target quality (height)\r\n * @param chunkNumber - Sequential index of the chunk\r\n * @param range - Optional byte range for partial content\r\n * @returns Promise resolving to a Readable stream\r\n */\r\n async streamChunk(\r\n videoId: string,\r\n quality: number,\r\n chunkNumber: number,\r\n range?: { start: number; end: number }\r\n ): Promise<Readable> {\r\n const chunkPath = this.getChunkPath(videoId, quality, chunkNumber);\r\n return this.streamManager.createStream(chunkPath, range);\r\n }\r\n\r\n private getChunkPath(videoId: string, quality: number, chunkNumber: number): string {\r\n return join(this.config.cacheDir, videoId, `${quality}p`, `chunk_${chunkNumber}.mp4`);\r\n }\r\n\r\n private getScreenshotPath(videoId: string, chunkNumber: number): string {\r\n return join(this.config.cacheDir, videoId, 'screenshots', `chunk_${chunkNumber}.jpg`);\r\n }\r\n\r\n private async generateVideoId(inputPath: string): Promise<string> {\r\n const stats = await fs.stat(inputPath);\r\n const fileName = inputPath.split(/[\\\\/]/).pop()?.split('.')[0];\r\n return `${fileName}_${Math.floor(stats.mtimeMs)}`;\r\n }\r\n}"],"names":["fs"],"mappings":"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"}
|
package/docs/README.md
CHANGED
|
@@ -7,11 +7,11 @@ Comprehensive documentation for the mes-engine video processing framework.
|
|
|
7
7
|
1. [Getting Started](#getting-started)
|
|
8
8
|
2. [Core Concepts](#core-concepts)
|
|
9
9
|
3. [Components](#components)
|
|
10
|
-
4. [HLS & Adaptive Streaming](
|
|
11
|
-
5. [Storage Providers](
|
|
12
|
-
6. [Caching Strategies](
|
|
10
|
+
4. [HLS & Adaptive Streaming](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/HLS.md)
|
|
11
|
+
5. [Storage Providers](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/storage.md)
|
|
12
|
+
6. [Caching Strategies](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/caching.md)
|
|
13
13
|
7. [Advanced Usage](#advanced-usage)
|
|
14
|
-
8. [API Reference](
|
|
14
|
+
8. [API Reference](https://github.com/Bum-Ho12/mes-engine/blob/main/docs/API.md)
|
|
15
15
|
|
|
16
16
|
## Getting Started
|
|
17
17
|
|
|
@@ -14,19 +14,16 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"../..": {
|
|
17
|
-
"version": "0.0
|
|
17
|
+
"version": "1.0.0",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"cors": "^2.8.5",
|
|
21
21
|
"express": "^5.2.1",
|
|
22
22
|
"fluent-ffmpeg": "^2.1.3",
|
|
23
23
|
"hls.js": "^1.6.15",
|
|
24
|
-
"lucide-react": "^0.562.0",
|
|
25
24
|
"morgan": "^1.10.1",
|
|
26
25
|
"multer": "^2.0.2",
|
|
27
26
|
"node-fetch": "^2.7.0",
|
|
28
|
-
"react": "^19.2.3",
|
|
29
|
-
"react-dom": "^19.2.3",
|
|
30
27
|
"tslib": "^2.8.1"
|
|
31
28
|
},
|
|
32
29
|
"devDependencies": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mes-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A powerful and flexible video processing framework for Node.js with support for multiple processing engines, adaptive streaming, and intelligent caching.",
|
|
6
6
|
"keywords": [
|
|
@@ -26,14 +26,9 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"cors": "^2.8.5",
|
|
28
28
|
"express": "^5.2.1",
|
|
29
|
-
"fluent-ffmpeg": "^2.1.3",
|
|
30
|
-
"hls.js": "^1.6.15",
|
|
31
|
-
"lucide-react": "^0.562.0",
|
|
32
29
|
"morgan": "^1.10.1",
|
|
33
30
|
"multer": "^2.0.2",
|
|
34
31
|
"node-fetch": "^2.7.0",
|
|
35
|
-
"react": "^19.2.3",
|
|
36
|
-
"react-dom": "^19.2.3",
|
|
37
32
|
"tslib": "^2.8.1"
|
|
38
33
|
},
|
|
39
34
|
"devDependencies": {
|
package/src/core/VideoEngine.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/engines/FFmpegEngine.ts
|
|
2
|
-
import { VideoEngine } from '../core/VideoEngine
|
|
3
|
-
import { QualityLevel } from '../core/types
|
|
2
|
+
import { VideoEngine } from '../core/VideoEngine';
|
|
3
|
+
import { QualityLevel } from '../core/types';
|
|
4
4
|
import { spawn } from 'child_process';
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import { dirname } from 'path';
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
export * from './core/types
|
|
3
|
-
export * from './core/events
|
|
4
|
-
export * from './core/VideoEngine
|
|
5
|
-
export * from './engines/FFmpegEngine
|
|
6
|
-
export * from './streaming/StreamManager
|
|
7
|
-
export * from './engines/GStreamerEngine
|
|
8
|
-
export * from './storage/StorageProvider
|
|
9
|
-
export * from './storage/FileSystemStorage
|
|
10
|
-
export * from './cache/cacheStrategy
|
|
11
|
-
export * from './cache/internalCache
|
|
12
|
-
export * from './cache/ExternalCache
|
|
13
|
-
export * from './processor
|
|
2
|
+
export * from './core/types';
|
|
3
|
+
export * from './core/events';
|
|
4
|
+
export * from './core/VideoEngine';
|
|
5
|
+
export * from './engines/FFmpegEngine';
|
|
6
|
+
export * from './streaming/StreamManager';
|
|
7
|
+
export * from './engines/GStreamerEngine';
|
|
8
|
+
export * from './storage/StorageProvider';
|
|
9
|
+
export * from './storage/FileSystemStorage';
|
|
10
|
+
export * from './cache/cacheStrategy';
|
|
11
|
+
export * from './cache/internalCache';
|
|
12
|
+
export * from './cache/ExternalCache';
|
|
13
|
+
export * from './processor';
|
package/src/processor.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/processor.ts
|
|
2
|
-
import { VideoEngine } from './core/VideoEngine
|
|
2
|
+
import { VideoEngine } from './core/VideoEngine';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
|
-
import { StorageProvider } from './storage/StorageProvider
|
|
5
|
-
import { StreamManager } from './streaming/StreamManager
|
|
6
|
-
import { VideoConfig, VideoManifest, VideoChunk, ProcessingOptions } from './core/types
|
|
4
|
+
import { StorageProvider } from './storage/StorageProvider';
|
|
5
|
+
import { StreamManager } from './streaming/StreamManager';
|
|
6
|
+
import { VideoConfig, VideoManifest, VideoChunk, ProcessingOptions } from './core/types';
|
|
7
7
|
import { join, dirname } from 'path';
|
|
8
8
|
import { promises as fs } from 'fs';
|
|
9
9
|
import { Readable } from 'stream';
|
|
10
|
-
import { VideoEvent } from './core/events
|
|
10
|
+
import { VideoEvent } from './core/events';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Main orchestrator for video processing.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/storage/FileSystemStorage.ts
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
|
-
import { StorageProvider } from './StorageProvider
|
|
3
|
+
import { StorageProvider } from './StorageProvider';
|
|
4
4
|
|
|
5
5
|
export class FileSystemStorage extends StorageProvider {
|
|
6
6
|
async saveChunk(chunkPath: string, data: Buffer): Promise<void> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/streaming/StreamManager.ts
|
|
2
2
|
import { Readable } from 'stream';
|
|
3
|
-
import { StorageProvider } from '../storage/StorageProvider
|
|
3
|
+
import { StorageProvider } from '../storage/StorageProvider';
|
|
4
4
|
|
|
5
5
|
export class StreamManager {
|
|
6
6
|
private storage: StorageProvider;
|