Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ jobs:
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-noble.list https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-noble.list
sudo apt update
sudo apt install vulkan-sdk -y
sudo apt-get install -y mesa-vulkan-drivers
sudo apt-get install -y mesa-vulkan-drivers libvulkan1

- name: Prepare Vulkan SDK for Ubuntu 22.04
if: contains(inputs.platform, 'ubuntu-22.04')
Expand All @@ -126,7 +126,7 @@ jobs:
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list
sudo apt update
sudo apt install vulkan-sdk -y
sudo apt-get install -y mesa-vulkan-drivers
sudo apt-get install -y mesa-vulkan-drivers libvulkan1

- name: install frontend dependencies
run: bun install
Expand Down Expand Up @@ -188,6 +188,42 @@ jobs:
releaseId: ${{ inputs.release-id }}
args: ${{ inputs.build-args }}

- name: Remove libwayland from AppImage
if: contains(inputs.platform, 'ubuntu')
run: |
# Install appimagetool if not available
if ! command -v appimagetool &> /dev/null; then
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
sudo mv appimagetool-x86_64.AppImage /usr/local/bin/appimagetool
fi

# Find the AppImage file
APPIMAGE_PATH=$(find $(pwd)/src-tauri/target/release/bundle/appimage -name "*.AppImage" -type f | head -1)

if [ -n "$APPIMAGE_PATH" ]; then
echo "Found AppImage: $APPIMAGE_PATH"

# Extract the AppImage
WORK_DIR=$(mktemp -d)
cd "$WORK_DIR"
"$APPIMAGE_PATH" --appimage-extract

# Remove libwayland libraries
find squashfs-root -name "*wayland*" -type f -delete
find squashfs-root -name "libwayland*" -type f -delete

# Rebuild the AppImage
appimagetool squashfs-root "$APPIMAGE_PATH"

# Clean up
rm -rf "$WORK_DIR"

echo "Successfully removed libwayland from AppImage"
else
echo "No AppImage found to process"
fi

- name: Upload artifacts (macOS)
if: inputs.upload-artifacts && contains(inputs.platform, 'macos')
uses: actions/upload-artifact@v4
Expand Down
10 changes: 10 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ default-run = "handy"
[profile.dev]
incremental = true # Compile your binary in smaller steps.

[profile.release]
strip = false
debug = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
Expand Down Expand Up @@ -58,6 +62,7 @@ tauri-plugin-fs = "2"
rustfft = "6.4.0"
strsim = "0.11.0"
natural = "0.5.0"
ash = "0.38.0"

[dependencies.ort-sys]
version = "=2.0.0-rc.9"
Expand All @@ -67,9 +72,11 @@ whisper-rs = { version = "0.14.4", features = ["metal", "log_backend"] }

[target.'cfg(target_os = "windows")'.dependencies]
whisper-rs = { version = "0.14.4", features = ["vulkan", "log_backend"] }
ash = "0.38.0"

[target.'cfg(target_os = "linux")'.dependencies]
whisper-rs = { version = "0.14.4", features = ["vulkan", "log_backend"] }
ash = "0.38.0"

[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-autostart = "2"
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod settings;
mod shortcut;
mod tray;
mod utils;
mod vulkan_detection;

use managers::audio::AudioRecordingManager;
use managers::model::ModelManager;
Expand Down
35 changes: 20 additions & 15 deletions src-tauri/src/managers/transcription.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::managers::model::ModelManager;
use crate::settings::get_settings;
use crate::vulkan_detection;
use anyhow::Result;
use natural::phonetics::soundex;
use serde::Serialize;
Expand Down Expand Up @@ -139,6 +140,9 @@ impl TranscriptionManager {
pub fn new(app: &App, model_manager: Arc<ModelManager>) -> Result<Self> {
let app_handle = app.app_handle().clone();

// Check Vulkan availability before initializing transcription
let _gpu_available = vulkan_detection::is_vulkan_available();

let manager = Self {
state: Mutex::new(None),
context: Mutex::new(None),
Expand Down Expand Up @@ -199,22 +203,23 @@ impl TranscriptionManager {
// Install log trampoline once per model load (safe to call multiple times)
install_logging_hooks();

// Create context parameters (GPU is guaranteed to be available)
let params = WhisperContextParameters::default();

// Create new context
let context =
WhisperContext::new_with_params(path_str, WhisperContextParameters::default())
.map_err(|e| {
let error_msg = format!("Failed to load whisper model {}: {}", model_id, e);
let _ = self.app_handle.emit(
"model-state-changed",
ModelStateEvent {
event_type: "loading_failed".to_string(),
model_id: Some(model_id.to_string()),
model_name: Some(model_info.name.clone()),
error: Some(error_msg.clone()),
},
);
anyhow::anyhow!(error_msg)
})?;
let context = WhisperContext::new_with_params(path_str, params).map_err(|e| {
let error_msg = format!("Failed to load whisper model {}: {}", model_id, e);
let _ = self.app_handle.emit(
"model-state-changed",
ModelStateEvent {
event_type: "loading_failed".to_string(),
model_id: Some(model_id.to_string()),
model_name: Some(model_info.name.clone()),
error: Some(error_msg.clone()),
},
);
anyhow::anyhow!(error_msg)
})?;

// Create new state
let state = context.create_state().map_err(|e| {
Expand Down
39 changes: 39 additions & 0 deletions src-tauri/src/vulkan_detection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
pub fn is_vulkan_available() -> bool {
#[cfg(any(target_os = "linux", target_os = "windows"))]
{
use ash::vk;

let result = unsafe {
let entry = match ash::Entry::load() {
Ok(e) => e,
Err(e) => {
eprintln!("Failed to load Vulkan entry: {:?}", e);
return false;
}
};

let app_desc =
vk::ApplicationInfo::default().api_version(vk::make_api_version(0, 1, 0, 0));
let instance_desc = vk::InstanceCreateInfo::default().application_info(&app_desc);

let instance = match entry.create_instance(&instance_desc, None) {
Ok(inst) => inst,
Err(e) => {
eprintln!("Failed to create Vulkan instance: {:?}", e);
return false;
}
};

instance.destroy_instance(None);
println!("Vulkan support is successfully checked and working.");
true
};

result
}
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
{
println!("Vulkan check skipped on this platform (macOS)");
true
}
}
Loading