test win codec fix

This commit is contained in:
Siddharth
2025-11-24 17:11:37 -07:00
parent 7129d55f86
commit 188ba94aad
7 changed files with 94 additions and 57 deletions
+5 -19
View File
@@ -143,18 +143,14 @@ function registerIpcHandlers(createEditorWindow2, createSourceSelectorWindow2, g
ipcMain.handle("store-recorded-video", async (_, videoData, fileName) => {
try {
const videoPath = path.join(RECORDINGS_DIR, fileName);
console.log("[STORE-VIDEO] Saving to:", videoPath);
console.log("[STORE-VIDEO] RECORDINGS_DIR:", RECORDINGS_DIR);
console.log("[STORE-VIDEO] Platform:", process.platform);
await fs.writeFile(videoPath, Buffer.from(videoData));
console.log("[STORE-VIDEO] Success! File size:", Buffer.from(videoData).length, "bytes");
return {
success: true,
path: videoPath,
message: "Video stored successfully"
};
} catch (error) {
console.error("[STORE-VIDEO] Failed to store video:", error);
console.error("Failed to store video:", error);
return {
success: false,
message: "Failed to store video",
@@ -164,23 +160,16 @@ function registerIpcHandlers(createEditorWindow2, createSourceSelectorWindow2, g
});
ipcMain.handle("get-recorded-video-path", async () => {
try {
console.log("[GET-VIDEO] RECORDINGS_DIR:", RECORDINGS_DIR);
console.log("[GET-VIDEO] Platform:", process.platform);
const files = await fs.readdir(RECORDINGS_DIR);
console.log("[GET-VIDEO] All files:", files);
const videoFiles = files.filter((file) => file.endsWith(".webm"));
console.log("[GET-VIDEO] Video files:", videoFiles);
if (videoFiles.length === 0) {
console.log("[GET-VIDEO] No video files found");
return { success: false, message: "No recorded video found" };
}
const latestVideo = videoFiles.sort().reverse()[0];
const videoPath = path.join(RECORDINGS_DIR, latestVideo);
console.log("[GET-VIDEO] Latest video path:", videoPath);
console.log("[GET-VIDEO] Path separators:", videoPath.includes("\\") ? "backslash" : "forward slash");
return { success: true, path: videoPath };
} catch (error) {
console.error("[GET-VIDEO] Failed to get video path:", error);
console.error("Failed to get video path:", error);
return { success: false, message: "Failed to get video path", error: String(error) };
}
});
@@ -252,13 +241,10 @@ async function cleanupOldRecordings() {
async function ensureRecordingsDir() {
try {
await fs.mkdir(RECORDINGS_DIR, { recursive: true });
console.log("=".repeat(60));
console.log("[STARTUP] Platform:", process.platform);
console.log("[STARTUP] RECORDINGS_DIR:", RECORDINGS_DIR);
console.log("[STARTUP] User Data Path:", app.getPath("userData"));
console.log("=".repeat(60));
console.log("RECORDINGS_DIR:", RECORDINGS_DIR);
console.log("User Data Path:", app.getPath("userData"));
} catch (error) {
console.error("[STARTUP] Failed to create recordings directory:", error);
console.error("Failed to create recordings directory:", error);
}
}
process.env.APP_ROOT = path.join(__dirname, "..");
+2 -14
View File
@@ -59,19 +59,14 @@ export function registerIpcHandlers(
ipcMain.handle('store-recorded-video', async (_, videoData: ArrayBuffer, fileName: string) => {
try {
const videoPath = path.join(RECORDINGS_DIR, fileName)
console.log('[STORE-VIDEO] Saving to:', videoPath)
console.log('[STORE-VIDEO] RECORDINGS_DIR:', RECORDINGS_DIR)
console.log('[STORE-VIDEO] Platform:', process.platform)
await fs.writeFile(videoPath, Buffer.from(videoData))
console.log('[STORE-VIDEO] Success! File size:', Buffer.from(videoData).length, 'bytes')
return {
success: true,
path: videoPath,
message: 'Video stored successfully'
}
} catch (error) {
console.error('[STORE-VIDEO] Failed to store video:', error)
console.error('Failed to store video:', error)
return {
success: false,
message: 'Failed to store video',
@@ -84,26 +79,19 @@ export function registerIpcHandlers(
ipcMain.handle('get-recorded-video-path', async () => {
try {
console.log('[GET-VIDEO] RECORDINGS_DIR:', RECORDINGS_DIR)
console.log('[GET-VIDEO] Platform:', process.platform)
const files = await fs.readdir(RECORDINGS_DIR)
console.log('[GET-VIDEO] All files:', files)
const videoFiles = files.filter(file => file.endsWith('.webm'))
console.log('[GET-VIDEO] Video files:', videoFiles)
if (videoFiles.length === 0) {
console.log('[GET-VIDEO] No video files found')
return { success: false, message: 'No recorded video found' }
}
const latestVideo = videoFiles.sort().reverse()[0]
const videoPath = path.join(RECORDINGS_DIR, latestVideo)
console.log('[GET-VIDEO] Latest video path:', videoPath)
console.log('[GET-VIDEO] Path separators:', videoPath.includes('\\') ? 'backslash' : 'forward slash')
return { success: true, path: videoPath }
} catch (error) {
console.error('[GET-VIDEO] Failed to get video path:', error)
console.error('Failed to get video path:', error)
return { success: false, message: 'Failed to get video path', error: String(error) }
}
})
+3 -6
View File
@@ -34,13 +34,10 @@ async function cleanupOldRecordings() {
async function ensureRecordingsDir() {
try {
await fs.mkdir(RECORDINGS_DIR, { recursive: true })
console.log('='.repeat(60))
console.log('[STARTUP] Platform:', process.platform)
console.log('[STARTUP] RECORDINGS_DIR:', RECORDINGS_DIR)
console.log('[STARTUP] User Data Path:', app.getPath('userData'))
console.log('='.repeat(60))
console.log('RECORDINGS_DIR:', RECORDINGS_DIR)
console.log('User Data Path:', app.getPath('userData'))
} catch (error) {
console.error('[STARTUP] Failed to create recordings directory:', error)
console.error('Failed to create recordings directory:', error)
}
}
+52 -3
View File
@@ -16,6 +16,7 @@
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@uiw/color-convert": "^2.9.2",
"@uiw/react-color-colorful": "^2.9.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -3728,9 +3729,9 @@
}
},
"node_modules/@uiw/color-convert": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.2.tgz",
"integrity": "sha512-ibw9OS29S7GlL+vDwU3p5XG3vhR7XdzUecydpZbakUeg2Td6nfsnrCAX9sbLwQ73p0abO42v+V4qRaWq+7/BjQ==",
"license": "MIT",
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
@@ -3757,6 +3758,18 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@uiw/react-color-alpha/node_modules/@uiw/color-convert": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
"license": "MIT",
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@babel/runtime": ">=7.19.0"
}
},
"node_modules/@uiw/react-color-colorful": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/react-color-colorful/-/react-color-colorful-2.9.0.tgz",
@@ -3777,6 +3790,18 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@uiw/react-color-colorful/node_modules/@uiw/color-convert": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
"license": "MIT",
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@babel/runtime": ">=7.19.0"
}
},
"node_modules/@uiw/react-color-hue": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/react-color-hue/-/react-color-hue-2.9.0.tgz",
@@ -3795,6 +3820,18 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@uiw/react-color-hue/node_modules/@uiw/color-convert": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
"license": "MIT",
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@babel/runtime": ">=7.19.0"
}
},
"node_modules/@uiw/react-color-saturation": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/react-color-saturation/-/react-color-saturation-2.9.0.tgz",
@@ -3813,6 +3850,18 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@uiw/react-color-saturation/node_modules/@uiw/color-convert": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
"license": "MIT",
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@babel/runtime": ">=7.19.0"
}
},
"node_modules/@uiw/react-drag-event-interactive": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-2.9.0.tgz",
+2 -1
View File
@@ -20,6 +20,7 @@
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@uiw/color-convert": "^2.9.2",
"@uiw/react-color-colorful": "^2.9.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -58,4 +59,4 @@
"vite-plugin-electron-renderer": "^0.14.5"
},
"main": "dist-electron/main.js"
}
}
@@ -49,41 +49,32 @@ export default function VideoEditor() {
// Helper to convert file path to proper file:// URL
const toFileUrl = (filePath: string): string => {
console.log('[VIDEO-EDITOR] Converting path to URL:', filePath);
// Normalize path separators to forward slashes
const normalized = filePath.replace(/\\/g, '/');
console.log('[VIDEO-EDITOR] Normalized path:', normalized);
// Check if it's a Windows absolute path (e.g., C:/Users/...)
if (normalized.match(/^[a-zA-Z]:/)) {
const fileUrl = `file:///${normalized}`;
console.log('[VIDEO-EDITOR] Windows file URL:', fileUrl);
return fileUrl;
}
// Unix-style absolute path
const fileUrl = `file://${normalized}`;
console.log('[VIDEO-EDITOR] Unix file URL:', fileUrl);
return fileUrl;
};
useEffect(() => {
async function loadVideo() {
try {
console.log('[VIDEO-EDITOR] Loading video...');
const result = await window.electronAPI.getRecordedVideoPath();
console.log('[VIDEO-EDITOR] getRecordedVideoPath result:', result);
if (result.success && result.path) {
const videoUrl = toFileUrl(result.path);
console.log('[VIDEO-EDITOR] Setting video path:', videoUrl);
setVideoPath(videoUrl);
} else {
console.error('[VIDEO-EDITOR] Failed to get video path:', result.message);
setError(result.message || 'Failed to load video');
}
} catch (err) {
console.error('[VIDEO-EDITOR] Error loading video:', err);
setError('Error loading video: ' + String(err));
} finally {
setLoading(false);
@@ -95,7 +86,6 @@ export default function VideoEditor() {
function togglePlayPause() {
const playback = videoPlaybackRef.current;
const video = playback?.video;
console.log('Toggle play/pause:', { hasVideo: !!video, isPlaying, action: isPlaying ? 'pause' : 'play' });
if (!playback || !video) return;
if (isPlaying) {
+30 -4
View File
@@ -205,7 +205,7 @@ export class VideoExporter {
const metadata: EncodedVideoChunkMetadata = {
decoderConfig: {
codec: this.config.codec || 'avc1.640033',
codec: this.config.codec || 'avc1.64001f',
codedWidth: this.config.width,
codedHeight: this.config.height,
description: this.videoDescription,
@@ -230,9 +230,9 @@ export class VideoExporter {
},
});
const codec = this.config.codec || 'avc1.640033';
const codec = this.config.codec || 'avc1.64001f';
this.encoder.configure({
const encoderConfig: VideoEncoderConfig = {
codec,
width: this.config.width,
height: this.config.height,
@@ -241,7 +241,33 @@ export class VideoExporter {
latencyMode: 'realtime',
bitrateMode: 'variable',
hardwareAcceleration: 'prefer-hardware',
} as VideoEncoderConfig);
};
try {
console.log('[VideoExporter] Configuring encoder with hardware acceleration...', {
codec,
resolution: `${this.config.width}x${this.config.height}`,
bitrate: this.config.bitrate,
framerate: this.config.frameRate,
});
this.encoder.configure(encoderConfig as VideoEncoderConfig);
console.log('[VideoExporter] Hardware encoder configured successfully');
} catch (error) {
console.warn('[VideoExporter] Hardware encoding failed, falling back to software encoding...', error);
// Fallback to software encoding if hardware fails
encoderConfig.hardwareAcceleration = 'prefer-software';
try {
this.encoder.configure(encoderConfig as VideoEncoderConfig);
console.log('[VideoExporter] Software encoder configured successfully');
} catch (softwareError) {
console.error('[VideoExporter] Software encoding also failed:', softwareError);
throw new Error(`Failed to initialize video encoder: ${softwareError instanceof Error ? softwareError.message : String(softwareError)}`);
}
}
}
cancel(): void {