This commit is contained in:
gpt-engineer-app[bot]
2025-12-21 13:39:53 +00:00
parent 614811167f
commit e23f6b55fb
3 changed files with 319 additions and 57 deletions
+45 -36
View File
@@ -95,42 +95,6 @@ export const useOfflineVideoExport = () => {
throw new Error('No video codec supported');
}
// Create audio context for recording
const recordingAudioContext = new AudioContext();
// Resume audio context if suspended
if (recordingAudioContext.state === 'suspended') {
await recordingAudioContext.resume();
}
// Create audio source and destination
const recordingAudioSource = recordingAudioContext.createBufferSource();
recordingAudioSource.buffer = audioBuffer;
recordingAudioSource.loop = false;
const audioDestination = recordingAudioContext.createMediaStreamDestination();
recordingAudioSource.connect(audioDestination);
recordingAudioSource.connect(recordingAudioContext.destination);
// Combine video and audio streams
const combinedStream = new MediaStream();
canvas.captureStream(fps).getVideoTracks().forEach(track => combinedStream.addTrack(track));
audioDestination.stream.getAudioTracks().forEach(track => combinedStream.addTrack(track));
console.log(`✅ Combined stream: ${combinedStream.getVideoTracks().length} video, ${combinedStream.getAudioTracks().length} audio tracks`);
const recorder = new MediaRecorder(combinedStream, {
mimeType: selectedCodec,
videoBitsPerSecond: videoBitsPerSecond,
});
console.log('✅ MediaRecorder created with audio and video');
recorder.start(1000); // 1 second chunks
// Start audio playback synchronized with recording
recordingAudioSource.start(0);
console.log('🔊 Audio playback started for recording');
// Use real audio data if available, otherwise generate mock data
let audioBuffer: AudioBuffer;
let sampleRate: number;
@@ -171,6 +135,51 @@ export const useOfflineVideoExport = () => {
console.log(`📊 Using mock audio: ${duration.toFixed(1)}s, ${totalSamples} samples`);
}
// Create audio context for recording
const recordingAudioContext = new AudioContext();
// Resume audio context if suspended
if (recordingAudioContext.state === 'suspended') {
await recordingAudioContext.resume();
}
// Create audio source and destination
const recordingAudioSource = recordingAudioContext.createBufferSource();
recordingAudioSource.buffer = audioBuffer;
recordingAudioSource.loop = false;
const audioDestination = recordingAudioContext.createMediaStreamDestination();
recordingAudioSource.connect(audioDestination);
recordingAudioSource.connect(recordingAudioContext.destination);
// Combine video and audio streams
const combinedStream = new MediaStream();
canvas.captureStream(fps).getVideoTracks().forEach(track => combinedStream.addTrack(track));
audioDestination.stream.getAudioTracks().forEach(track => combinedStream.addTrack(track));
console.log(`✅ Combined stream: ${combinedStream.getVideoTracks().length} video, ${combinedStream.getAudioTracks().length} audio tracks`);
// Chunks array to collect recorded data
const chunks: Blob[] = [];
const recorder = new MediaRecorder(combinedStream, {
mimeType: selectedCodec,
videoBitsPerSecond: videoBitsPerSecond,
});
recorder.ondataavailable = (e) => {
if (e.data.size > 0) {
chunks.push(e.data);
}
};
console.log('✅ MediaRecorder created with audio and video');
recorder.start(1000); // 1 second chunks
// Start audio playback synchronized with recording
recordingAudioSource.start(0);
console.log('🔊 Audio playback started for recording');
// Generate animation frames for full audio duration
const totalFrames = Math.ceil(duration * fps);
const samplesPerFrame = Math.min(qualityConfig.samplesPerFrame, Math.floor(totalSamples / totalFrames));