diff --git a/Cargo.toml b/Cargo.toml
index 5cd7519..392aeb3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "tauri-video02"
-version = "0.1.0"
+version = "0.1.1"
description = "A Tauri Video App"
authors = ["sinus@sasedev.net"]
edition = "2024"
diff --git a/frontend/index.html b/frontend/index.html
index d553262..e740851 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,6 +4,8 @@
+
Tauri GST Record + Preview
diff --git a/frontend/main.ts b/frontend/main.ts
index f906cfb..ee56837 100644
--- a/frontend/main.ts
+++ b/frontend/main.ts
@@ -58,8 +58,8 @@ async function refreshPreviewFrame(): Promise {
try {
const encoded = await invoke("get_video_preview_frame_base64");
- if (encoded !== null && encoded.length > 0 && videoPreview) {
- videoPreview.src = `data:image/jpeg;base64,${encoded}`;
+ if (encoded !== null && encoded.length > 0) {
+ updatePreviewImageFromBase64(encoded);
}
} catch (error) {
console.error("preview refresh failed", error);
@@ -73,6 +73,12 @@ function startPreviewPolling(): void {
return;
}
+ console.log("starting preview polling");
+
+ window.setTimeout(() => {
+ void refreshPreviewFrame();
+ }, 120);
+
previewTimer = window.setInterval(() => {
void refreshPreviewFrame();
}, 200);
@@ -87,6 +93,11 @@ function stopPreviewPolling(): void {
previewRequestInFlight = false;
if (videoPreview)
videoPreview.removeAttribute("src");
+
+ if (previewObjectUrl !== null) {
+ URL.revokeObjectURL(previewObjectUrl);
+ previewObjectUrl = null;
+ }
}
startAudioBtn.addEventListener("click", async () => {
@@ -142,4 +153,35 @@ stopVideoBtn.addEventListener("click", async () => {
setVideoStatus(`Stop video failed.\n${String(error)}`);
setVideoButtons(true);
}
-});
\ No newline at end of file
+});
+
+let previewObjectUrl: string | null = null;
+
+function base64ToUint8Array(base64: string): Uint8Array {
+ const binary = window.atob(base64);
+ const bytes = new Uint8Array(binary.length);
+
+ for (let index = 0;index < binary.length;index += 1) {
+ bytes[index] = binary.charCodeAt(index);
+ }
+
+ return bytes;
+}
+
+function updatePreviewImageFromBase64(encoded: string): void {
+ const bytes = base64ToUint8Array(encoded);
+ const copied = new Uint8Array(bytes.byteLength);
+
+ copied.set(bytes);
+
+ const blob = new Blob([copied.buffer], { type: "image/jpeg" });
+ const objectUrl = URL.createObjectURL(blob);
+
+ if (previewObjectUrl !== null) {
+ URL.revokeObjectURL(previewObjectUrl);
+ }
+
+ previewObjectUrl = objectUrl;
+ if (videoPreview)
+ videoPreview.src = objectUrl;
+}
diff --git a/frontend/styles.css b/frontend/styles.css
index 181a556..235ed51 100644
--- a/frontend/styles.css
+++ b/frontend/styles.css
@@ -45,6 +45,7 @@ button:disabled {
.preview-wrap {
width: 100%;
aspect-ratio: 16/9;
+ min-height: 240px;
background: #0b1220;
border: 1px solid #374151;
border-radius: 8px;
diff --git a/package.json b/package.json
index 6b75b5e..f8a9ec1 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "tauri-video02",
"private": true,
- "version": "0.1.0",
+ "version": "0.1.1",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src/media_video.rs b/src/media_video.rs
index 2304b11..7c74417 100644
--- a/src/media_video.rs
+++ b/src/media_video.rs
@@ -52,7 +52,7 @@ fn build_pipeline(output_path: &std::path::Path) -> Result {
@@ -284,9 +286,12 @@ pub fn get_video_preview_frame_base64(
};
let Some(bytes) = guard.as_ref() else {
+ tracing::info!("preview frame requested but none is available yet");
return Ok(None);
};
+ tracing::info!(size = bytes.len(), "preview frame requested and returned");
+
let encoded = base64::engine::general_purpose::STANDARD.encode(bytes);
Ok(Some(encoded))
}
diff --git a/tauri.conf.json b/tauri.conf.json
index 0afed27..0753bbb 100644
--- a/tauri.conf.json
+++ b/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "tauri-video02",
- "version": "0.1.0",
+ "version": "0.1.1",
"identifier": "com.sinus.tauri-video02",
"build": {
"beforeDevCommand": "npm run dev",