Skip to main content

ffmpeg-webcli-browser-video-editor

A browser-based video editor powered by ffmpeg.wasm for client-side video processing without server uploads

الانتقال إلى التثبيت

معلومات المصدر

المستودع
reason-machines/devtools-skills
آخر نشاط في المصدر
٥ يونيو ٢٠٢٦ في ٠٦:٥٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
ffmpeg-webcli-browser-video-editor
description
A browser-based video editor powered by ffmpeg.wasm for client-side video processing without server uploads
triggers
["how do I use ffmpeg webCLI to process videos in the browser","set up ffmpeg.wasm video editor in my web app","convert videos to GIF using ffmpeg webCLI","process videos client-side with WebAssembly","integrate browser-based video editing with ffmpeg","use ffmpeg webCLI API for video operations","implement offline video processing in the browser","create video editor with ffmpeg.wasm"]
# ffmpeg webCLI Browser Video Editor > Skill by [ara.so](https://ara.so) — Devtools Skills collection. ffmpeg webCLI is a browser-based video editor powered by ffmpeg.wasm that processes videos entirely client-side using WebAssembly. No server uploads, no backend infrastructure — all video processing happens locally in the user's browser. It supports 30+ video operations including GIF creation, format conversion, compression, trimming, filters, effects, and more. ## Installation ### Option 1: Use the Live App Access the hosted version directly: ``` https://tejaswigowda.com/ffmpeg-webCLI/ ``` ### Option 2: Clone and Run Locally ```bash git clone https://github.com/tejaswigowda/ffmpeg-webCLI.git cd ffmpeg-webCLI # Serve the files with any static server python -m http.server 8000 # or npx serve . ``` ### Option 3: Integrate into Your Project The project uses ffmpeg.wasm as its core dependency. To integrate similar functionality: ```html <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/@ffmpeg/ffmpeg@0.12.7/dist/umd/ffmpeg.js"></script> </head> <body> <input type="file" id="videoInput" accept="video/*"> <button id="processBtn">Process Video</button> <video id="output" controls></video> <script src="app.js"></script> </body> </html> ``` ## Core Architecture ffmpeg webCLI uses: - **ffmpeg.wasm** — WebAssembly port of ffmpeg for browser execution - **Web Workers** — Background processing to keep UI responsive - **PWA** — Progressive Web App for offline support - **Wake Lock API** — Prevents screen sleep during processing ## Key Components ### 1. Initialize ffmpeg.wasm ```javascript const { FFmpeg } = FFmpegWASM; const { fetchFile } = FFmpegWASM; let ffmpeg = null; let loaded = false; async function loadFFmpeg() { if (loaded) return; ffmpeg = new FFmpeg(); // Log ffmpeg output ffmpeg.on('log', ({ message }) => { console.log(message); }); // Track progress ffmpeg.on('progress', ({ progress, time }) => { console.log(`Progress: ${Math.round(progress * 100)}%`); updateProgressBar(progress); }); // Load the core and wasm files await ffmpeg.load({ coreURL: 'https://unpkg.com/@ffmpeg/core@0.12.4/dist/umd/ffmpeg-core.js', wasmURL: 'https://unpkg.com/@ffmpeg/core@0.12.4/dist/umd/ffmpeg-core.wasm', }); loaded = true; console.log('FFmpeg loaded successfully'); } ``` ### 2. Load Video File into Virtual Filesystem ```javascript async function loadVideoFile(file) { await loadFFmpeg(); // Write file to ffmpeg's virtual filesystem await ffmpeg.writeFile('input.mp4', await fetchFile(file)); console.log('Video loaded into virtual filesystem'); } ``` ### 3. Convert Video to GIF ```javascript async function convertToGIF(inputFile, width = 480, fps = 10) { await loadVideoFile(inputFile); // Two-pass palette generation for best quality // Pass 1: Generate palette await ffmpeg.exec([ '-i', 'input.mp4', '-vf', `fps=${fps},scale=${width}:-1:flags=lanczos,palettegen`, 'palette.png' ]); // Pass 2: Use palette to create GIF await ffmpeg.exec([ '-i', 'input.mp4', '-i', 'palette.png', '-filter_complex', `fps=${fps},scale=${width}:-1:flags=lanczos[x];[x][1:v]paletteuse`, 'output.gif' ]); // Read the output file const data = await ffmpeg.readFile('output.gif'); return new Blob([data.buffer], { type: 'image/gif' }); } ``` ### 4. Convert Video Format ```javascript async function convertFormat(inputFile, outputFormat = 'mp4') { await loadVideoFile(inputFile); const outputFile = `output.${outputFormat}`; const formatConfigs = { mp4: ['-c:v', 'libx264', '-c:a', 'aac'], webm: ['-c:v', 'libvpx-vp9', '-c:a', 'libopus'], mkv: ['-c:v', 'libx264', '-c:a', 'aac'], mov: ['-c:v', 'libx264', '-c:a', 'aac'], avi: ['-c:v', 'libx264', '-c:a', 'aac'] }; await ffmpeg.exec([ '-i', 'input.mp4', ...formatConfigs[outputFormat], outputFile ]); const data = await ffmpeg.readFile(outputFile); return new Blob([data.buffer], { type: `video/${outputFormat}` }); } ``` ### 5. Compress Video with CRF ```javascript async function compressVideo(inputFile, crf = 23, preset = 'medium') { await loadVideoFile(inputFile); // CRF: 18 (near lossless) to 51 (maximum compression) // Preset: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow await ffmpeg.exec([ '-i', 'input.mp4', '-c:v', 'libx264', '-crf', crf.toString(), '-preset', preset, '-c:a', 'aac', 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 6. Trim Video ```javascript async function trimVideo(inputFile, startTime, endTime) { await loadVideoFile(inputFile); const duration = endTime - startTime; await ffmpeg.exec([ '-ss', startTime.toString(), '-i', 'input.mp4', '-t', duration.toString(), '-c', 'copy', // Stream copy for fast, lossless trim 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 7. Extract Audio ```javascript async function extractAudio(inputFile, format = 'mp3') { await loadVideoFile(inputFile); const outputFile = `output.${format}`; const audioConfigs = { mp3: ['-c:a', 'libmp3lame', '-q:a', '2'], aac: ['-c:a', 'aac', '-b:a', '192k'], wav: ['-c:a', 'pcm_s16le'], ogg: ['-c:a', 'libvorbis', '-q:a', '5'], flac: ['-c:a', 'flac'] }; await ffmpeg.exec([ '-i', 'input.mp4', '-vn', // No video ...audioConfigs[format], outputFile ]); const data = await ffmpeg.readFile(outputFile); return new Blob([data.buffer], { type: `audio/${format}` }); } ``` ### 8. Resize Video ```javascript async function resizeVideo(inputFile, width, height = -1) { await loadVideoFile(inputFile); // height = -1 maintains aspect ratio await ffmpeg.exec([ '-i', 'input.mp4', '-vf', `scale=${width}:${height}`, '-c:v', 'libx264', '-crf', '23', '-c:a', 'copy', 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 9. Change Video Speed ```javascript async function changeSpeed(inputFile, speedMultiplier) { await loadVideoFile(inputFile); const videoPTS = 1 / speedMultiplier; // Build atempo filter chain (each atempo can only do 0.5-2.0x) let atempoChain = ''; let remaining = speedMultiplier; while (remaining > 2.0) { atempoChain += 'atempo=2.0,'; remaining /= 2.0; } while (remaining < 0.5) { atempoChain += 'atempo=0.5,'; remaining /= 0.5; } atempoChain += `atempo=${remaining.toFixed(3)}`; await ffmpeg.exec([ '-i', 'input.mp4', '-filter:v', `setpts=${videoPTS}*PTS`, '-filter:a', atempoChain, '-c:v', 'libx264', '-crf', '23', 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 10. Rotate Video ```javascript async function rotateVideo(inputFile, rotation) { await loadVideoFile(inputFile); const rotations = { '90cw': 'transpose=1', '90ccw': 'transpose=2', '180': 'transpose=1,transpose=1', 'hflip': 'hflip', 'vflip': 'vflip', 'both': 'hflip,vflip' }; await ffmpeg.exec([ '-i', 'input.mp4', '-vf', rotations[rotation], '-c:a', 'copy', 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 11. Add Watermark/Logo ```javascript async function addWatermark(inputFile, logoFile, position = 'bottom-right', widthPercent = 15) { await loadVideoFile(inputFile); await ffmpeg.writeFile('logo.png', await fetchFile(logoFile)); const positions = { 'top-left': '10:10', 'top-right': 'W-w-10:10', 'bottom-left': '10:H-h-10', 'bottom-right': 'W-w-10:H-h-10', 'center': '(W-w)/2:(H-h)/2' }; const scaleFilter = `[1:v]scale=iw*${widthPercent/100}:-1[logo]`; const overlayFilter = `[0:v][logo]overlay=${positions[position]}`; await ffmpeg.exec([ '-i', 'input.mp4', '-i', 'logo.png', '-filter_complex', `${scaleFilter};${overlayFilter}`, '-c:a', 'copy', 'output.mp4' ]); const data = await ffmpeg.readFile('output.mp4'); return new Blob([data.buffer], { type: 'video/mp4' }); } ``` ### 12. Adjust Brightness/Contrast/Saturation ```javascript async function adjustColors(inputFile, brightness = 0, contrast = 1, saturation = 1, grayscale = false) { await loadVideoFile(inputFile); const sat = grayscale ? 0 : saturation; await ffmpeg.exec([ '-i', 'input.mp4',
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub