UNPKG

@profullstack/transcoder

Version:

A server-side module for transcoding videos, audio, and images using FFmpeg with smart presets and optimizations

704 lines (661 loc) 15.5 kB
/** * @profullstack/transcoder - Smart Presets * * This file contains pre-configured settings optimized for specific platforms and use cases. * These presets make it easy to transcode videos for different platforms with a single setting. */ /** * Instagram Preset * - Max video length: 60 seconds (feed), 15 seconds (stories) * - Recommended resolution: 1080x1080 (square), 1080x1920 (vertical) * - Aspect ratio: 1:1 (square), 4:5 (vertical), 16:9 (horizontal) * - Video codec: H.264 * - Audio codec: AAC * - Max file size: 100MB */ export const INSTAGRAM_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '3500k', audioBitrate: '128k', preset: 'medium', profile: 'main', level: '4.0', pixelFormat: 'yuv420p', movflags: '+faststart', // Square format by default (can be overridden) width: 1080, height: 1080 }; /** * Instagram Stories Preset * - Max video length: 15 seconds * - Recommended resolution: 1080x1920 (vertical) * - Aspect ratio: 9:16 * - Video codec: H.264 * - Audio codec: AAC */ export const INSTAGRAM_STORIES_PRESET = { ...INSTAGRAM_PRESET, width: 1080, height: 1920 }; /** * YouTube HD Preset * - Recommended resolution: 1920x1080 (1080p) * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Recommended bitrate: 8000-12000 kbps */ export const YOUTUBE_HD_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '8000k', audioBitrate: '384k', preset: 'slow', // Higher quality encoding profile: 'high', level: '4.2', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1920, height: 1080, fps: 30 }; /** * YouTube 4K Preset * - Recommended resolution: 3840x2160 (4K) * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Recommended bitrate: 35000-45000 kbps */ export const YOUTUBE_4K_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '40000k', audioBitrate: '384k', preset: 'slow', // Higher quality encoding profile: 'high', level: '5.1', pixelFormat: 'yuv420p', movflags: '+faststart', width: 3840, height: 2160, fps: 30 }; /** * Twitter Preset * - Max video length: 140 seconds * - Recommended resolution: 1280x720 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Max file size: 512MB */ export const TWITTER_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '5000k', audioBitrate: '128k', preset: 'medium', profile: 'main', level: '4.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1280, height: 720, fps: 30 }; /** * Facebook Preset * - Recommended resolution: 1280x720 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Recommended bitrate: 3000-4000 kbps */ export const FACEBOOK_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '4000k', audioBitrate: '128k', preset: 'medium', profile: 'main', level: '4.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1280, height: 720, fps: 30 }; /** * TikTok Preset * - Recommended resolution: 1080x1920 (vertical) * - Aspect ratio: 9:16 * - Video codec: H.264 * - Audio codec: AAC */ export const TIKTOK_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '5000k', audioBitrate: '128k', preset: 'medium', profile: 'main', level: '4.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1080, height: 1920, fps: 30 }; /** * Vimeo HD Preset * - Recommended resolution: 1920x1080 (1080p) * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Recommended bitrate: 8000-10000 kbps */ export const VIMEO_HD_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '10000k', audioBitrate: '320k', preset: 'slow', // Higher quality encoding profile: 'high', level: '4.2', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1920, height: 1080, fps: 30 }; /** * Web Optimized Preset * - Recommended resolution: 1280x720 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Optimized for fast loading and streaming */ export const WEB_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '2500k', audioBitrate: '128k', preset: 'fast', profile: 'main', level: '4.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1280, height: 720, fps: 30 }; /** * Mobile Optimized Preset * - Recommended resolution: 640x360 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Optimized for mobile devices and slower connections */ export const MOBILE_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '1000k', audioBitrate: '96k', preset: 'fast', profile: 'baseline', level: '3.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 640, height: 360, fps: 30 }; /** * HD Optimized Preset * - Recommended resolution: 1920x1080 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Optimized for high-quality playback on large screens */ export const HD_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '6000k', audioBitrate: '192k', preset: 'medium', profile: 'high', level: '4.1', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1920, height: 1080, fps: 30 }; /** * Tablet Optimized Preset * - Recommended resolution: 1280x720 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Optimized for tablet devices with medium-speed connections */ export const TABLET_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '2000k', audioBitrate: '128k', preset: 'medium', profile: 'main', level: '3.1', pixelFormat: 'yuv420p', movflags: '+faststart', width: 1280, height: 720, fps: 30 }; /** * Low Bandwidth Preset * - Recommended resolution: 480x270 * - Aspect ratio: 16:9 * - Video codec: H.264 * - Audio codec: AAC * - Optimized for very slow connections */ export const LOW_BANDWIDTH_PRESET = { videoCodec: 'libx264', audioCodec: 'aac', videoBitrate: '500k', audioBitrate: '64k', preset: 'fast', profile: 'baseline', level: '3.0', pixelFormat: 'yuv420p', movflags: '+faststart', width: 480, height: 270, fps: 24 }; /** * Audio Presets for different quality levels and use cases */ /** * High Quality Audio Preset * - Audio codec: AAC * - Bitrate: 320k * - Sample rate: 48000 Hz * - Channels: 2 (stereo) * - Optimized for high-quality music and professional audio */ export const AUDIO_HIGH_QUALITY_PRESET = { audioCodec: 'aac', audioBitrate: '320k', audioSampleRate: 48000, audioChannels: 2, audioProfile: 'aac_low', normalize: false }; /** * Medium Quality Audio Preset * - Audio codec: AAC * - Bitrate: 192k * - Sample rate: 44100 Hz * - Channels: 2 (stereo) * - Good balance between quality and file size */ export const AUDIO_MEDIUM_QUALITY_PRESET = { audioCodec: 'aac', audioBitrate: '192k', audioSampleRate: 44100, audioChannels: 2, audioProfile: 'aac_low', normalize: false }; /** * Low Quality Audio Preset * - Audio codec: AAC * - Bitrate: 96k * - Sample rate: 44100 Hz * - Channels: 2 (stereo) * - Optimized for smaller file size */ export const AUDIO_LOW_QUALITY_PRESET = { audioCodec: 'aac', audioBitrate: '96k', audioSampleRate: 44100, audioChannels: 2, audioProfile: 'aac_low', normalize: false }; /** * Voice Optimized Audio Preset * - Audio codec: AAC * - Bitrate: 128k * - Sample rate: 44100 Hz * - Channels: 1 (mono) * - Optimized for voice recordings, podcasts, etc. */ export const AUDIO_VOICE_PRESET = { audioCodec: 'aac', audioBitrate: '128k', audioSampleRate: 44100, audioChannels: 1, audioProfile: 'aac_low', normalize: true }; /** * MP3 High Quality Preset * - Audio codec: libmp3lame * - Bitrate: 320k * - Sample rate: 44100 Hz * - Channels: 2 (stereo) * - Optimized for high-quality MP3 files */ export const MP3_HIGH_QUALITY_PRESET = { audioCodec: 'libmp3lame', audioBitrate: '320k', audioSampleRate: 44100, audioChannels: 2, normalize: false }; /** * MP3 Medium Quality Preset * - Audio codec: libmp3lame * - Bitrate: 192k * - Sample rate: 44100 Hz * - Channels: 2 (stereo) * - Good balance between quality and file size for MP3 */ export const MP3_MEDIUM_QUALITY_PRESET = { audioCodec: 'libmp3lame', audioBitrate: '192k', audioSampleRate: 44100, audioChannels: 2, normalize: false }; /** * MP3 Low Quality Preset * - Audio codec: libmp3lame * - Bitrate: 96k * - Sample rate: 44100 Hz * - Channels: 2 (stereo) * - Optimized for smaller file size MP3 */ export const MP3_LOW_QUALITY_PRESET = { audioCodec: 'libmp3lame', audioBitrate: '96k', audioSampleRate: 44100, audioChannels: 2, normalize: false }; /** * Image Presets for different quality levels and use cases */ /** * High Quality JPEG Preset * - Format: JPEG * - Quality: 95 * - Optimized for high-quality images with minimal compression artifacts */ export const JPEG_HIGH_QUALITY_PRESET = { format: 'jpg', quality: 95, optimize: true }; /** * Medium Quality JPEG Preset * - Format: JPEG * - Quality: 85 * - Good balance between quality and file size */ export const JPEG_MEDIUM_QUALITY_PRESET = { format: 'jpg', quality: 85, optimize: true }; /** * Low Quality JPEG Preset * - Format: JPEG * - Quality: 70 * - Optimized for smaller file size */ export const JPEG_LOW_QUALITY_PRESET = { format: 'jpg', quality: 70, optimize: true }; /** * WebP High Quality Preset * - Format: WebP * - Quality: 90 * - Optimized for high-quality images with better compression than JPEG */ export const WEBP_HIGH_QUALITY_PRESET = { format: 'webp', quality: 90, optimize: true }; /** * WebP Medium Quality Preset * - Format: WebP * - Quality: 80 * - Good balance between quality and file size */ export const WEBP_MEDIUM_QUALITY_PRESET = { format: 'webp', quality: 80, optimize: true }; /** * WebP Low Quality Preset * - Format: WebP * - Quality: 65 * - Optimized for smaller file size */ export const WEBP_LOW_QUALITY_PRESET = { format: 'webp', quality: 65, optimize: true }; /** * PNG Preset * - Format: PNG * - Lossless compression * - Optimized for images with transparency or sharp edges */ export const PNG_PRESET = { format: 'png', compressionLevel: 6, optimize: true }; /** * PNG Optimized Preset * - Format: PNG * - Higher compression level for smaller file size * - Still lossless, but slower encoding */ export const PNG_OPTIMIZED_PRESET = { format: 'png', compressionLevel: 9, optimize: true }; /** * AVIF High Quality Preset * - Format: AVIF * - Quality: 80 * - Modern image format with excellent compression */ export const AVIF_HIGH_QUALITY_PRESET = { format: 'avif', quality: 80, speed: 4, optimize: true }; /** * AVIF Medium Quality Preset * - Format: AVIF * - Quality: 60 * - Good balance between quality and file size */ export const AVIF_MEDIUM_QUALITY_PRESET = { format: 'avif', quality: 60, speed: 6, optimize: true }; /** * Thumbnail Preset * - Format: JPEG * - Quality: 80 * - Resize to 300x300 (maintaining aspect ratio) * - Optimized for thumbnails */ export const THUMBNAIL_PRESET = { format: 'jpg', quality: 80, resize: { width: 300, height: 300, fit: 'inside' }, optimize: true }; /** * Social Media Preset * - Format: JPEG * - Quality: 90 * - Resize to 1200x630 (common social media size) * - Optimized for social media sharing */ export const SOCIAL_MEDIA_PRESET = { format: 'jpg', quality: 90, resize: { width: 1200, height: 630, fit: 'cover' }, optimize: true }; /** * Square Image Preset * - Format: PNG (to support transparency) * - Quality: High * - Converts any image to square format with padding * - Maintains original aspect ratio * - Adds transparent padding where needed */ export const SQUARE_PRESET = { format: 'png', squarePad: true, padColor: 'transparent', optimize: true }; /** * Square Image with White Background Preset * - Format: JPEG * - Quality: 90 * - Converts any image to square format with padding * - Maintains original aspect ratio * - Adds white padding where needed */ export const SQUARE_WHITE_PRESET = { format: 'jpg', quality: 90, squarePad: true, padColor: 'white', optimize: true }; /** * Instagram Square Preset * - Format: JPEG * - Quality: 90 * - Size: 1080x1080 (Instagram square format) * - Maintains original aspect ratio with padding * - Optimized for Instagram */ export const INSTAGRAM_SQUARE_PRESET = { format: 'jpg', quality: 90, width: 1080, height: 1080, squarePad: true, padColor: 'white', optimize: true }; /** * Map of preset names to preset configurations */ export const PRESETS = { 'instagram': INSTAGRAM_PRESET, 'instagram-stories': INSTAGRAM_STORIES_PRESET, 'youtube-hd': YOUTUBE_HD_PRESET, 'youtube-4k': YOUTUBE_4K_PRESET, 'twitter': TWITTER_PRESET, 'facebook': FACEBOOK_PRESET, 'tiktok': TIKTOK_PRESET, 'vimeo-hd': VIMEO_HD_PRESET, 'web': WEB_PRESET, 'mobile': MOBILE_PRESET, 'hd': HD_PRESET, 'tablet': TABLET_PRESET, 'low-bandwidth': LOW_BANDWIDTH_PRESET, // Audio presets 'audio-high': AUDIO_HIGH_QUALITY_PRESET, 'audio-medium': AUDIO_MEDIUM_QUALITY_PRESET, 'audio-low': AUDIO_LOW_QUALITY_PRESET, 'audio-voice': AUDIO_VOICE_PRESET, 'mp3-high': MP3_HIGH_QUALITY_PRESET, 'mp3-medium': MP3_MEDIUM_QUALITY_PRESET, 'mp3-low': MP3_LOW_QUALITY_PRESET, // Image presets 'jpeg-high': JPEG_HIGH_QUALITY_PRESET, 'jpeg-medium': JPEG_MEDIUM_QUALITY_PRESET, 'jpeg-low': JPEG_LOW_QUALITY_PRESET, 'webp-high': WEBP_HIGH_QUALITY_PRESET, 'webp-medium': WEBP_MEDIUM_QUALITY_PRESET, 'webp-low': WEBP_LOW_QUALITY_PRESET, 'png': PNG_PRESET, 'png-optimized': PNG_OPTIMIZED_PRESET, 'avif-high': AVIF_HIGH_QUALITY_PRESET, 'avif-medium': AVIF_MEDIUM_QUALITY_PRESET, 'thumbnail': THUMBNAIL_PRESET, 'social-media': SOCIAL_MEDIA_PRESET, 'square': SQUARE_PRESET, 'square-white': SQUARE_WHITE_PRESET, 'instagram-square': INSTAGRAM_SQUARE_PRESET }; /** * Responsive profile sets for different use cases */ export const RESPONSIVE_PROFILES = { 'standard': ['mobile', 'web', 'hd'], 'comprehensive': ['low-bandwidth', 'mobile', 'tablet', 'web', 'hd'], 'minimal': ['mobile', 'web'], 'social': ['mobile', 'instagram', 'twitter', 'facebook'], 'professional': ['web', 'vimeo-hd', 'youtube-hd'] }; /** * Get a preset configuration by name * * @param {string} presetName - The name of the preset to retrieve * @returns {Object|null} - The preset configuration or null if not found */ export function getPreset(presetName) { if (!presetName || typeof presetName !== 'string') { return null; } const normalizedName = presetName.toLowerCase(); return PRESETS[normalizedName] || null; } /** * Get a responsive profile set by name * * @param {string} profileSetName - The name of the responsive profile set to retrieve * @returns {Array<string>|null} - Array of profile names or null if not found */ export function getResponsiveProfileSet(profileSetName) { if (!profileSetName || typeof profileSetName !== 'string') { return null; } const normalizedName = profileSetName.toLowerCase(); return RESPONSIVE_PROFILES[normalizedName] || null; }