Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 3,092 Bytes
2ed47da |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
import { rm, mkdir, writeFile, readFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import ffmpeg from "fluent-ffmpeg";
import { getRandomDirectory } from "../files/getRandomDirectory.mts";
/**
* Converts an image in Base64 format to a video encoded in Base64.
*
* @param inputImageInBase64 - The input image encoded in Base64.
* @param outputVideoFormat - Optional. Format of the output video (default is "mp4").
* @param outputVideoDurationInMs - Optional. Duration of the video in milliseconds (default is 1000ms).
* @param codec - Optional. Codec used for video coding. Defaults differ based on `outputVideoFormat`.
* @param width - Optional. Width of the output video.
* @param height - Optional. Height of the output video.
* @param fps - Optional. Frame rate of the output video.
*
* @returns - A promise that resolves to the video as a Base64 encoded string.
*/
export async function imageToVideoBase64({
inputImageInBase64,
outputFilePath,
outputDir,
clearOutputDirAtTheEnd = true,
outputVideoFormat = "mp4",
outputVideoDurationInMs = 1000,
codec = outputVideoFormat === "webm" ? "libvpx-vp9" : "libx264",
width = 1920,
height = 1080,
fps = 25
}: {
inputImageInBase64: string
outputFilePath?: string
outputDir?: string
clearOutputDirAtTheEnd?: boolean
outputVideoFormat?: string
outputVideoDurationInMs?: number
codec?: string
width?: number
height?: number
fps?: number
}): Promise<string> {
outputDir = outputDir || (await getRandomDirectory())
// Decode the Base64 image and write it to a temporary file.
const base64Data = inputImageInBase64.substring(inputImageInBase64.indexOf(',') + 1);
const buffer = Buffer.from(base64Data, 'base64');
const inputImagePath = path.join(outputDir, 'inputImage.png');
await writeFile(inputImagePath, buffer);
// Set the path for the output video.
outputFilePath = outputFilePath || path.join(outputDir, `output.${outputVideoFormat}`);
const durationInSeconds = outputVideoDurationInMs / 1000;
// Process the image to video conversion using ffmpeg.
await new Promise<void>((resolve, reject) => {
ffmpeg(inputImagePath)
.outputOptions([
`-t ${durationInSeconds}`,
`-r ${fps}`,
`-s ${width}x${height}`, // set frame size
`-c:v ${codec}`, // set the codec
'-tune stillimage',
'-pix_fmt yuv420p'
])
.on('end', () => resolve())
.on('error', (err) => reject(err))
.save(outputFilePath);
});
// Read the video file, encode it to Base64, and format it as a data URI.
const videoBuffer = await readFile(outputFilePath);
const videoBase64 = videoBuffer.toString('base64');
const resultAsBase64DataUri = `data:video/${outputVideoFormat};base64,${videoBase64}`;
// Attempt to clean up temporary work files.
if (clearOutputDirAtTheEnd) {
try {
await rm(outputDir, { recursive: true, force: true });
} catch (error) {
console.error('Error removing temporary files:', error);
}
}
return resultAsBase64DataUri;
} |