test win codec fix
This commit is contained in:
+5
-19
@@ -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, "..");
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+52
-3
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user