mirror of
https://github.com/DeNNiiInc/Web-Page-Performance-Test.git
synced 2026-04-18 12:05:59 +00:00
68 lines
2.5 KiB
JavaScript
68 lines
2.5 KiB
JavaScript
const ffmpeg = require('fluent-ffmpeg');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
const { v4: uuidv4 } = require('uuid');
|
|
|
|
/**
|
|
* Creates an MP4 video from an array of frame objects.
|
|
* @param {Array} frames - Array of { data: base64 } objects
|
|
* @param {number} outputFps - Frames per second
|
|
* @returns {Promise<string>} - Path to generated video file
|
|
*/
|
|
async function createVideoFromFrames(frames, outputFps = 10) {
|
|
if (!frames || frames.length === 0) throw new Error('No frames provided');
|
|
|
|
// Filter out invalid frames if any
|
|
const validFrames = frames.filter(f => f && f.data);
|
|
if (validFrames.length === 0) throw new Error('No valid frames found');
|
|
|
|
const tempDir = path.join(os.tmpdir(), 'frames-' + uuidv4());
|
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
|
|
try {
|
|
// Save frames as images
|
|
for (let i = 0; i < validFrames.length; i++) {
|
|
const frame = validFrames[i];
|
|
// Remove header if present
|
|
const base64Data = frame.data.replace(/^data:image\/\w+;base64,/, "");
|
|
const buffer = Buffer.from(base64Data, 'base64');
|
|
const filePath = path.join(tempDir, `frame-${i.toString().padStart(5, '0')}.jpg`);
|
|
fs.writeFileSync(filePath, buffer);
|
|
}
|
|
|
|
const outputPath = path.join(os.tmpdir(), `video-${uuidv4()}.mp4`);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
ffmpeg()
|
|
.input(path.join(tempDir, 'frame-%05d.jpg'))
|
|
.inputFPS(outputFps)
|
|
.output(outputPath)
|
|
.outputOptions([
|
|
'-c:v libx264',
|
|
'-pix_fmt yuv420p',
|
|
'-crf 23',
|
|
'-preset fast',
|
|
'-movflags +faststart' // Optimize for web playback
|
|
])
|
|
.on('end', () => {
|
|
// Cleanup frames
|
|
try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch(e) {}
|
|
resolve(outputPath);
|
|
})
|
|
.on('error', (err) => {
|
|
// Cleanup frames
|
|
try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch(e) {}
|
|
console.error('FFmpeg video generation error:', err);
|
|
reject(err);
|
|
})
|
|
.run();
|
|
});
|
|
} catch (e) {
|
|
try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch(err) {}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
module.exports = { createVideoFromFrames };
|