Add Core ML alert for Whisper models to inform users about performance improvements and first-run optimization time

This commit is contained in:
Beingpax 2025-04-09 21:37:29 +05:45
parent 0a5f688338
commit aabbf03f60
2 changed files with 64 additions and 10 deletions

View File

@ -7,11 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
E136D0112DA3EE57000E1E8A /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = E136D0102DA3EE57000E1E8A /* whisper.xcframework */; };
E136D0122DA3EE57000E1E8A /* whisper.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E136D0102DA3EE57000E1E8A /* whisper.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E1A261122CC143AC00B233D1 /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = E1A261112CC143AC00B233D1 /* KeyboardShortcuts */; };
E1ADD45A2CC5352A00303ECB /* LaunchAtLogin in Frameworks */ = {isa = PBXBuildFile; productRef = E1ADD4592CC5352A00303ECB /* LaunchAtLogin */; };
E1ADD45F2CC544F100303ECB /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = E1ADD45E2CC544F100303ECB /* Sparkle */; };
E1F5FA752DA6CBD700B1FD8A /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = E136D0102DA3EE57000E1E8A /* whisper.xcframework */; };
E1F5FA762DA6CBD700B1FD8A /* whisper.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E136D0102DA3EE57000E1E8A /* whisper.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E1F5FA7A2DA6CBF900B1FD8A /* Zip in Frameworks */ = {isa = PBXBuildFile; productRef = E1F5FA792DA6CBF900B1FD8A /* Zip */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -32,13 +33,13 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
E136D00D2DA3EBE0000E1E8A /* Embed Frameworks */ = {
E1F5FA772DA6CBD700B1FD8A /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
E136D0122DA3EE57000E1E8A /* whisper.xcframework in Embed Frameworks */,
E1F5FA762DA6CBD700B1FD8A /* whisper.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -75,10 +76,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E136D0112DA3EE57000E1E8A /* whisper.xcframework in Frameworks */,
E1F5FA752DA6CBD700B1FD8A /* whisper.xcframework in Frameworks */,
E1ADD45A2CC5352A00303ECB /* LaunchAtLogin in Frameworks */,
E1ADD45F2CC544F100303ECB /* Sparkle in Frameworks */,
E1A261122CC143AC00B233D1 /* KeyboardShortcuts in Frameworks */,
E1F5FA7A2DA6CBF900B1FD8A /* Zip in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -138,7 +140,7 @@
E11473AC2CBE0F0A00318EE4 /* Sources */,
E11473AD2CBE0F0A00318EE4 /* Frameworks */,
E11473AE2CBE0F0A00318EE4 /* Resources */,
E136D00D2DA3EBE0000E1E8A /* Embed Frameworks */,
E1F5FA772DA6CBD700B1FD8A /* Embed Frameworks */,
);
buildRules = (
);
@ -152,6 +154,7 @@
E1A261112CC143AC00B233D1 /* KeyboardShortcuts */,
E1ADD4592CC5352A00303ECB /* LaunchAtLogin */,
E1ADD45E2CC544F100303ECB /* Sparkle */,
E1F5FA792DA6CBF900B1FD8A /* Zip */,
);
productName = VoiceInk;
productReference = E11473B02CBE0F0A00318EE4 /* VoiceInk.app */;
@ -239,6 +242,7 @@
E1A261102CC143AC00B233D1 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */,
E1ADD4582CC5352A00303ECB /* XCRemoteSwiftPackageReference "LaunchAtLogin-Modern" */,
E1ADD45D2CC544F100303ECB /* XCRemoteSwiftPackageReference "Sparkle" */,
E1F5FA782DA6CBF900B1FD8A /* XCRemoteSwiftPackageReference "Zip" */,
);
preferredProjectObjectVersion = 77;
productRefGroup = E11473B12CBE0F0A00318EE4 /* Products */;
@ -442,7 +446,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 120;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
DEVELOPMENT_TEAM = V6J6A3VWY2;
ENABLE_HARDENED_RUNTIME = YES;
@ -457,7 +461,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.20;
MARKETING_VERSION = 1.21;
PRODUCT_BUNDLE_IDENTIFIER = com.prakashjoshipax.VoiceInk;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@ -475,7 +479,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 120;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
DEVELOPMENT_TEAM = V6J6A3VWY2;
ENABLE_HARDENED_RUNTIME = YES;
@ -490,7 +494,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.20;
MARKETING_VERSION = 1.21;
PRODUCT_BUNDLE_IDENTIFIER = com.prakashjoshipax.VoiceInk;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@ -632,6 +636,14 @@
minimumVersion = 2.6.4;
};
};
E1F5FA782DA6CBF900B1FD8A /* XCRemoteSwiftPackageReference "Zip" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/marmelroy/Zip?tab=readme-ov-file";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.1.2;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@ -650,6 +662,11 @@
package = E1ADD45D2CC544F100303ECB /* XCRemoteSwiftPackageReference "Sparkle" */;
productName = Sparkle;
};
E1F5FA792DA6CBF900B1FD8A /* Zip */ = {
isa = XCSwiftPackageProductDependency;
package = E1F5FA782DA6CBF900B1FD8A /* XCRemoteSwiftPackageReference "Zip" */;
productName = Zip;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = E11473A82CBE0F0A00318EE4 /* Project object */;

View File

@ -116,9 +116,46 @@ extension WhisperState {
}
}
// Shows an alert about Core ML support and first-run optimization
private func showCoreMLAlert(for model: PredefinedModel, completion: @escaping () -> Void) {
Task { @MainActor in
let alert = NSAlert()
alert.messageText = "Core ML Support for \(model.displayName) Model"
alert.informativeText = "This Whisper model supports Core ML, which can improve performance by 2-4x on Apple Silicon devices.\n\nDuring the first run, it can take several minutes to optimize the model for your system. Subsequent runs will be much faster."
alert.alertStyle = .informational
alert.addButton(withTitle: "Download")
alert.addButton(withTitle: "Cancel")
let response = alert.runModal()
if response == .alertFirstButtonReturn {
completion()
}
}
}
func downloadModel(_ model: PredefinedModel) async {
guard let url = URL(string: model.downloadURL) else { return }
// Check if model supports Core ML (non-quantized models)
let supportsCoreML = !model.name.contains("q5") && !model.name.contains("q8")
if supportsCoreML {
// Show the CoreML alert for models that support it
await MainActor.run {
showCoreMLAlert(for: model) {
// This completion handler is called when user clicks "Download"
Task {
await self.performModelDownload(model, url)
}
}
}
} else {
// Directly download the model if it doesn't support Core ML
await performModelDownload(model, url)
}
}
private func performModelDownload(_ model: PredefinedModel, _ url: URL) async {
do {
let whisperModel = try await downloadMainModel(model, from: url)