Export to m4b from WAV efficiently
This commit is contained in:
parent
79d2e7f613
commit
4a2d75e155
4 changed files with 10 additions and 23 deletions
|
|
@ -87,26 +87,16 @@ export async function POST(request: NextRequest) {
|
|||
await mkdir(intermediateDir);
|
||||
}
|
||||
|
||||
// First, write each chapter to a temporary file and get its duration
|
||||
// Process each chapter - no need for initial conversion since input is WAV
|
||||
const chapterFiles: { path: string; title: string; duration: number }[] = [];
|
||||
let currentTime = 0;
|
||||
|
||||
for (let i = 0; i < data.chapters.length; i++) {
|
||||
const chapter = data.chapters[i];
|
||||
const inputPath = join(intermediateDir, `${i}-input.aac`);
|
||||
const outputPath = join(intermediateDir, `${i}.wav`);
|
||||
|
||||
// Write the chapter audio to a temp file
|
||||
await writeFile(inputPath, Buffer.from(new Uint8Array(chapter.buffer)));
|
||||
|
||||
// Convert to WAV with consistent format (this helps with timestamp issues)
|
||||
await runFFmpeg([
|
||||
'-i', inputPath,
|
||||
'-acodec', 'pcm_s16le',
|
||||
'-ar', '44100',
|
||||
'-ac', '2',
|
||||
outputPath
|
||||
]);
|
||||
// Write the chapter audio directly since it's already WAV
|
||||
await writeFile(outputPath, Buffer.from(new Uint8Array(chapter.buffer)));
|
||||
|
||||
// Get the duration of this chapter
|
||||
const duration = await getAudioDuration(outputPath);
|
||||
|
|
@ -116,9 +106,6 @@ export async function POST(request: NextRequest) {
|
|||
title: chapter.title,
|
||||
duration
|
||||
});
|
||||
|
||||
// Clean up input file
|
||||
await unlink(inputPath).catch(console.error);
|
||||
}
|
||||
|
||||
// Create chapter metadata file
|
||||
|
|
@ -129,7 +116,7 @@ export async function POST(request: NextRequest) {
|
|||
);
|
||||
|
||||
// Calculate chapter timings based on actual durations
|
||||
chapterFiles.forEach((chapter, index) => {
|
||||
chapterFiles.forEach((chapter) => {
|
||||
const startMs = Math.floor(currentTime * 1000);
|
||||
currentTime += chapter.duration;
|
||||
const endMs = Math.floor(currentTime * 1000);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ export async function POST(req: NextRequest) {
|
|||
voice: voice as "alloy",
|
||||
input: text,
|
||||
speed: speed,
|
||||
response_format: format === 'aac' ? 'aac' : 'mp3',
|
||||
// Use wav format for audiobook generation to avoid initial conversion
|
||||
response_format: format === 'audiobook' ? 'wav' : (format === 'aac' ? 'aac' : 'mp3'),
|
||||
}, { signal: req.signal }); // Pass the abort signal to OpenAI client
|
||||
|
||||
// Get the audio data as array buffer
|
||||
|
|
@ -37,7 +38,7 @@ export async function POST(req: NextRequest) {
|
|||
const stream = response.body;
|
||||
|
||||
// Return audio data with appropriate headers
|
||||
const contentType = format === 'aac' ? 'audio/aac' : 'audio/mpeg';
|
||||
const contentType = format === 'audiobook' ? 'audio/wav' : (format === 'aac' ? 'audio/aac' : 'audio/mpeg');
|
||||
return new NextResponse(stream, {
|
||||
headers: {
|
||||
'Content-Type': contentType
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ export function EPUBProvider({ children }: { children: ReactNode }) {
|
|||
text: text.trim(),
|
||||
voice: voice,
|
||||
speed: voiceSpeed,
|
||||
format: 'aac'
|
||||
format: 'audiobook' // Request WAV format directly
|
||||
}),
|
||||
signal
|
||||
});
|
||||
|
|
@ -244,7 +244,7 @@ export function EPUBProvider({ children }: { children: ReactNode }) {
|
|||
let spineIndex = processedSections;
|
||||
let currentSpineHref: string | undefined;
|
||||
|
||||
spine.each((item: any) => {
|
||||
spine.each((item: SpineItem) => {
|
||||
if (spineIndex === 0) {
|
||||
currentSpineHref = item.href;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import {
|
|||
} from '@/utils/pdf';
|
||||
|
||||
import type { PDFDocumentProxy } from 'pdfjs-dist';
|
||||
import { useParams } from 'next/navigation';
|
||||
|
||||
/**
|
||||
* Interface defining all available methods and properties in the PDF context
|
||||
|
|
@ -234,7 +233,7 @@ export function PDFProvider({ children }: { children: ReactNode }) {
|
|||
text: text.trim(),
|
||||
voice: voice,
|
||||
speed: voiceSpeed,
|
||||
format: 'aac'
|
||||
format: 'audiobook' // Request WAV format directly
|
||||
}),
|
||||
signal
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue