Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 2,359 Bytes
2cae2a9 |
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 |
import { tmpdir } from "node:os"
import { join } from "node:path"
import { mkdtemp } from "node:fs/promises"
import { v4 as uuidv4 } from "uuid"
import { ClapProject } from "./core/clap/types.mts";
import { concatenateAudio } from "./core/ffmpeg/concatenateAudio.mts";
import { concatenateVideosWithAudio } from "./core/ffmpeg/concatenateVideosWithAudio.mts";
import { writeBase64ToFile } from "./core/files/writeBase64ToFile.mts";
import { concatenateVideos } from "./core/ffmpeg/concatenateVideos.mts"
import { deleteFilesWithName } from "./core/files/deleteFileWithName.mts"
/**
* Generate a .mp4 video inside a direcory (if none is provided, it will be created in /tmp)
*
* @param clap
* @returns file path to the final .mp4
*/
export async function clapToTmpVideoFilePath(clap: ClapProject, dir = ""): Promise<string> {
dir = dir || (await mkdtemp(join(tmpdir(), uuidv4())))
const videoFilePaths: string[] = []
const videoSegments = clap.segments.filter(s => s.category === "video" && s.assetUrl.startsWith("data:video/"))
for (const segment of videoSegments) {
videoFilePaths.push(
await writeBase64ToFile(
segment.assetUrl,
join(dir, `tmp_asset_${segment.id}.mp4`)
)
)
}
const concatenatedVideosNoSound = await concatenateVideos({
videoFilePaths,
output: join(dir, `tmp_asset_concatenated_videos.mp4`)
})
const audioTracks: string[] = []
const musicSegments = clap.segments.filter(s => s.category === "music" && s.assetUrl.startsWith("data:audio/"))
for (const segment of musicSegments) {
audioTracks.push(
await writeBase64ToFile(
segment.assetUrl,
join(dir, `tmp_asset_${segment.id}.wav`)
)
)
}
const concatenatedAudio = await concatenateAudio({
output: join(dir, `tmp_asset_concatenated_audio.wav`),
audioTracks,
crossfadeDurationInSec: 2 // 2 seconds
})
const finalFilePathOfVideoWithSound = await concatenateVideosWithAudio({
output: join(dir, `final_video.mp4`),
audioFilePath: concatenatedAudio.filepath,
videoFilePaths: [concatenatedVideosNoSound.filepath],
// videos are silent, so they can stay at 0
videoTracksVolume: 0.0,
audioTrackVolume: 1.0,
})
// we delete all the temporary assets
await deleteFilesWithName(dir, `tmp_asset_`)
return finalFilePathOfVideoWithSound
} |