feat: compression 20
This commit is contained in:
@@ -10,7 +10,7 @@ const COMPRESSION_ROOT = "/app/data/compression";
|
|||||||
const ORIGINALS_ROOT = "/originals";
|
const ORIGINALS_ROOT = "/originals";
|
||||||
const COMPRESSION_JOB_FILE = "job.json";
|
const COMPRESSION_JOB_FILE = "job.json";
|
||||||
|
|
||||||
export type CompressionJobStatus = "compressed" | "replacing" | "replaced";
|
export type CompressionJobStatus = "compressing" | "compressed" | "replacing" | "replaced";
|
||||||
|
|
||||||
export interface CompressionJob {
|
export interface CompressionJob {
|
||||||
version: 1;
|
version: 1;
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ export const runLoggedFfmpegCommand = async (
|
|||||||
log.write(`Command: ${resolvedCommand}\n\n`);
|
log.write(`Command: ${resolvedCommand}\n\n`);
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
const child = spawn(resolvedCommand, { shell: true });
|
// Replace the shell with FFmpeg so `close` signals the encoder's completion.
|
||||||
|
const child = spawn(`exec ${resolvedCommand}`, { shell: true });
|
||||||
let stderrTail = "";
|
let stderrTail = "";
|
||||||
let settled = false;
|
let settled = false;
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (job.ownerId !== currentUser.id) continue;
|
if (job.ownerId !== currentUser.id) continue;
|
||||||
|
if (job.status === "compressing") continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const outputPath = path.join(getCompressionDirectory(job.sourceAssetId), job.outputFileName);
|
const outputPath = path.join(getCompressionDirectory(job.sourceAssetId), job.outputFileName);
|
||||||
|
|||||||
@@ -38,18 +38,32 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
const inputPath = getOriginalAssetPath(asset.originalPath);
|
const inputPath = getOriginalAssetPath(asset.originalPath);
|
||||||
const outputPath = getCompressionOutputPath(asset.id, asset.originalFileName);
|
const outputPath = getCompressionOutputPath(asset.id, asset.originalFileName);
|
||||||
|
const outputFileName = outputPath.split("/").pop() || `${asset.id}-compressed.mp4`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await clearCompressionDirectory(asset.id);
|
await clearCompressionDirectory(asset.id);
|
||||||
await ensureCompressionDirectory(asset.id);
|
await ensureCompressionDirectory(asset.id);
|
||||||
|
|
||||||
const originalStat = await stat(inputPath);
|
const originalStat = await stat(inputPath);
|
||||||
|
await writeCompressionJob({
|
||||||
|
version: 1,
|
||||||
|
ownerId: currentUser.id,
|
||||||
|
sourceAssetId: asset.id,
|
||||||
|
originalFileName: asset.originalFileName,
|
||||||
|
originalPath: asset.originalPath,
|
||||||
|
localDateTime: asset.localDateTime.toISOString(),
|
||||||
|
originalSize: originalStat.size,
|
||||||
|
outputFileName,
|
||||||
|
compressedSize: 0,
|
||||||
|
compressedAt: new Date().toISOString(),
|
||||||
|
status: "compressing",
|
||||||
|
});
|
||||||
|
|
||||||
const command = await getFfmpegCommand(currentUser.id);
|
const command = await getFfmpegCommand(currentUser.id);
|
||||||
const runLoggedFfmpegCommand: typeof runFfmpegCommand =
|
const runLoggedFfmpegCommand: typeof runFfmpegCommand =
|
||||||
(await import("@/helpers/ffmpeg-log.server")).runLoggedFfmpegCommand;
|
(await import("@/helpers/ffmpeg-log.server")).runLoggedFfmpegCommand;
|
||||||
await runLoggedFfmpegCommand(command, inputPath, outputPath);
|
await runLoggedFfmpegCommand(command, inputPath, outputPath);
|
||||||
const outputStat = await stat(outputPath);
|
const outputStat = await stat(outputPath);
|
||||||
const outputFileName = outputPath.split("/").pop() || `${asset.id}-compressed.mp4`;
|
|
||||||
|
|
||||||
await writeCompressionJob({
|
await writeCompressionJob({
|
||||||
version: 1,
|
version: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user