mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-13 00:10:27 +00:00
feat: ffmpeg
This commit is contained in:
104
src/common/ffmpeg.ts
Normal file
104
src/common/ffmpeg.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { FFmpeg } from '@ffmpeg.wasm/main';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { LogWrapper } from './log';
|
||||
|
||||
class FFmpegService {
|
||||
private ffmpegRef: FFmpeg;
|
||||
|
||||
constructor(ffmpegRef: FFmpeg) {
|
||||
this.ffmpegRef = ffmpegRef;
|
||||
}
|
||||
|
||||
public async extractThumbnail(videoPath: string, thumbnailPath: string): Promise<void> {
|
||||
const videoFileName = `${randomUUID()}.mp4`;
|
||||
const outputFileName = `${randomUUID()}.jpg`;
|
||||
try {
|
||||
this.ffmpegRef.fs.writeFile(videoFileName, readFileSync(videoPath));
|
||||
let code = await this.ffmpegRef.run('-i', videoFileName, '-ss', '00:00:01.000', '-vframes', '1', outputFileName);
|
||||
if (code! === 0) {
|
||||
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code);
|
||||
}
|
||||
const thumbnail = this.ffmpegRef.fs.readFile(outputFileName);
|
||||
writeFileSync(thumbnailPath, thumbnail);
|
||||
} catch (error) {
|
||||
console.error('Error extracting thumbnail:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(outputFileName);
|
||||
} catch (unlinkError) {
|
||||
console.error('Error unlinking output file:', unlinkError);
|
||||
}
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(videoFileName);
|
||||
} catch (unlinkError) {
|
||||
console.error('Error unlinking video file:', unlinkError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async convertFile(inputFile: string, outputFile: string, format: string): Promise<void> {
|
||||
const inputFileName = `${randomUUID()}.pcm`;
|
||||
const outputFileName = `${randomUUID()}.${format}`;
|
||||
try {
|
||||
this.ffmpegRef.fs.writeFile(inputFileName, readFileSync(inputFile));
|
||||
const params = format === 'amr'
|
||||
? ['-f', 's16le', '-ar', '24000', '-ac', '1', '-i', inputFileName, '-ar', '8000', '-b:a', '12.2k', outputFileName]
|
||||
: ['-f', 's16le', '-ar', '24000', '-ac', '1', '-i', inputFileName, outputFileName];
|
||||
let code = await this.ffmpegRef.run(...params);
|
||||
if (code! === 0) {
|
||||
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code);
|
||||
}
|
||||
const outputData = this.ffmpegRef.fs.readFile(outputFileName);
|
||||
writeFileSync(outputFile, outputData);
|
||||
} catch (error) {
|
||||
console.error('Error converting file:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(outputFileName);
|
||||
} catch (unlinkError) {
|
||||
console.error('Error unlinking output file:', unlinkError);
|
||||
}
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(inputFileName);
|
||||
} catch (unlinkError) {
|
||||
console.error('Error unlinking input file:', unlinkError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async convert(filePath: string, pcmPath: string, logger: LogWrapper): Promise<Buffer> {
|
||||
const inputFileName = `${randomUUID()}.input`;
|
||||
const outputFileName = `${randomUUID()}.pcm`;
|
||||
try {
|
||||
this.ffmpegRef.fs.writeFile(inputFileName, readFileSync(filePath));
|
||||
const params = ['-y', '-i', inputFileName, '-ar', '24000', '-ac', '1', '-f', 's16le', outputFileName];
|
||||
let code = await this.ffmpegRef.run(...params);
|
||||
if (code! === 0) {
|
||||
throw new Error('FFmpeg process exited with code ' + code);
|
||||
}
|
||||
const outputData = this.ffmpegRef.fs.readFile(outputFileName);
|
||||
writeFileSync(pcmPath, outputData);
|
||||
return Buffer.from(outputData);
|
||||
} catch (error: any) {
|
||||
logger.log('FFmpeg处理转换出错: ', error.message);
|
||||
throw error;
|
||||
} finally {
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(outputFileName);
|
||||
} catch (unlinkError) {
|
||||
logger.log('Error unlinking output file:', unlinkError);
|
||||
}
|
||||
try {
|
||||
this.ffmpegRef.fs.unlink(inputFileName);
|
||||
} catch (unlinkError) {
|
||||
logger.log('Error unlinking input file:', unlinkError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' });
|
||||
export const ffmpegService = new FFmpegService(ffmpegInstance);
|
||||
Reference in New Issue
Block a user