Skip to main content

Architecture

Frame’s backend is built with Rust and Tauri, providing a high-performance media conversion engine. The backend communicates with the frontend through Tauri’s Inter-Process Communication (IPC) system, exposing commands that can be invoked from JavaScript/TypeScript.

Available Tauri Commands

The following commands are registered in the Tauri application (lib.rs:156-167):

Conversion Commands

  • queue_conversion - Queue a media conversion task
  • pause_conversion - Pause a running conversion
  • resume_conversion - Resume a paused conversion
  • cancel_conversion - Cancel a conversion task
  • probe_media - Probe media file metadata
  • get_max_concurrency - Get current maximum concurrent conversions
  • set_max_concurrency - Update maximum concurrent conversions

System Commands

  • get_available_encoders - Query available hardware encoders
  • open_native_file_dialog - Open native file picker
  • ask_native_dialog - Display native confirmation dialog
  • close_splash - Close splash screen window

IPC Communication Model

Frame uses Tauri’s command system for synchronous request-response patterns and event emission for asynchronous updates.

Command Invocation (Frontend)

import { invoke } from '@tauri-apps/api/core';

// Queue a conversion
await invoke('queue_conversion', {
  id: 'task-123',
  filePath: '/path/to/video.mp4',
  outputName: 'converted',
  config: { /* ConversionConfig */ }
});

Event Listening (Frontend)

import { listen } from '@tauri-apps/api/event';

// Listen for conversion progress
await listen('conversion-progress', (event) => {
  console.log(`Progress: ${event.payload.progress}%`);
});

Event Types

The backend emits the following events:
  • conversion-started - Task has started processing
  • conversion-progress - Progress update (0-100)
  • conversion-completed - Task completed successfully
  • conversion-error - Task failed with error
  • conversion-log - FFmpeg log output

Error Handling

All commands return Result<T, ConversionError> types. The ConversionError enum (error.rs:4-22) defines all possible error types:

ConversionError Types

Shell
String
Shell command execution failed. Contains the error message from the failed command.
Io
std::io::Error
I/O operation failed (file read/write, directory access, etc.).
Json
serde_json::Error
JSON parsing or serialization failed (typically during FFprobe output parsing).
Channel
String
Internal channel communication error between manager and workers.
Probe
String
Media file probing failed. Contains stderr output from FFprobe.
Worker
String
FFmpeg worker process error during conversion.
InvalidInput
String
Invalid input parameters or configuration. Contains specific validation error message.
TaskNotFound
String
Attempted to pause/resume/cancel a task that doesn’t exist or isn’t running.

Error Serialization

Errors are automatically serialized to strings when sent to the frontend:
try {
  await invoke('queue_conversion', { /* ... */ });
} catch (error) {
  // error is a string like "Invalid input: End time must be greater than start time"
  console.error(error);
}

Type System

All types use serde for serialization with camelCase field names when communicating with the frontend:
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConversionConfig {
    pub processing_mode: String,
    pub video_codec: String,
    // ...
}

State Management

The backend maintains a ConversionManager as managed state throughout the application lifecycle:
app.manage(conversion::ConversionManager::new(app.handle().clone()));
Commands can access this state using tauri::State:
pub async fn queue_conversion(
    manager: tauri::State<'_, ConversionManager>,
    // ...
)

Build docs developers (and LLMs) love