-
-
Notifications
You must be signed in to change notification settings - Fork 226
Add Parallel Mode transcription with Settings UI toggle and ~/Documents model discovery #273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "hex-app": patch | ||
| --- | ||
|
|
||
| Add Parallel Mode transcription with Settings UI toggle and ~/Documents model discovery |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,3 +21,7 @@ node_modules/ | |
|
|
||
| # Claude | ||
| .claude/ | ||
|
|
||
| # Test artifacts | ||
| test_audio/ | ||
|
|
||
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
HexCore/Tests/HexCoreTests/ParallelModeAndSettingsTests.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import XCTest | ||
| @testable import HexCore | ||
|
|
||
| final class ParallelModeAndSettingsTests: XCTestCase { | ||
| func testDefaultSettingsHaveParallelModeDisabledByDefault() { | ||
| let settings = HexSettings() | ||
| XCTAssertEqual(settings.transcribeMode, .default) | ||
| XCTAssertNil(settings.customModelDirectory) | ||
| } | ||
|
|
||
| func testParallelModeSettingRoundTripSerialization() throws { | ||
| var settings = HexSettings() | ||
| settings.transcribeMode = .parallel | ||
| settings.customModelDirectory = "/Users/test/Documents/models" | ||
|
|
||
| let encoder = JSONEncoder() | ||
| let data = try encoder.encode(settings) | ||
|
|
||
| let decoder = JSONDecoder() | ||
| let decoded = try decoder.decode(HexSettings.self, from: data) | ||
|
|
||
| XCTAssertEqual(decoded.transcribeMode, .parallel) | ||
| XCTAssertEqual(decoded.customModelDirectory, "/Users/test/Documents/models") | ||
| XCTAssertEqual(decoded, settings) | ||
| } | ||
|
|
||
| func testDecodingJsonPayloadWithParallelTranscribeMode() throws { | ||
| let jsonString = """ | ||
| { | ||
| "transcribeMode": "parallel", | ||
| "customModelDirectory": "/Users/test/Documents" | ||
| } | ||
| """ | ||
| guard let data = jsonString.data(using: .utf8) else { | ||
| XCTFail("Failed to convert JSON string to Data") | ||
| return | ||
| } | ||
|
|
||
| let decoded = try JSONDecoder().decode(HexSettings.self, from: data) | ||
| XCTAssertEqual(decoded.transcribeMode, .parallel) | ||
| XCTAssertEqual(decoded.customModelDirectory, "/Users/test/Documents") | ||
| } | ||
|
|
||
| func testTranscriptionModeEnumCasesAndRawValues() { | ||
| XCTAssertEqual(TranscriptionMode.default.rawValue, "default") | ||
| XCTAssertEqual(TranscriptionMode.parallel.rawValue, "parallel") | ||
| XCTAssertEqual(TranscriptionMode.allCases.count, 2) | ||
| } | ||
|
|
||
| func testModelPatternMatcherResolvesExactMatch() { | ||
| let match = ModelPatternMatcher.matches("openai_whisper-base", "openai_whisper-base") | ||
| XCTAssertTrue(match) | ||
| } | ||
|
|
||
| func testModelPatternMatcherResolvesWildcardMatch() { | ||
| let match = ModelPatternMatcher.matches("openai_whisper-*", "openai_whisper-large-v3-v20240930_turbo_632MB") | ||
| XCTAssertTrue(match) | ||
| } | ||
|
|
||
| func testModelPatternMatcherResolvesDownloadedPreference() { | ||
| let models = [ | ||
| (name: "openai_whisper-large-v3", isDownloaded: false), | ||
| (name: "openai_whisper-large-v3_turbo", isDownloaded: true) | ||
| ] | ||
| let resolved = ModelPatternMatcher.resolvePattern("openai_whisper-large-v3*", from: models) | ||
| XCTAssertEqual(resolved, "openai_whisper-large-v3_turbo") | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
WhisperKit DecodingOptions concurrentWorkerCount 0 meaning default value💡 Result:
In WhisperKit, the concurrentWorkerCount property within DecodingOptions determines the number of audio chunks processed in parallel [1][2]. A value of 0 (or in some older versions, the absence of an explicit setting) has historically been interpreted as a signal to process all available audio chunks in a single batch, or effectively without a specific cap on concurrency [3]. However, recent updates have moved toward setting a specific default value to manage memory usage [4]. As of the current implementation, the default value for concurrentWorkerCount is 16 [4]. This change was introduced to cap peak memory consumption, particularly for long audio files when using Voice Activity Detection (VAD) chunking, preventing devices from running out of memory by limiting the number of concurrent asynchronous CoreML predictions [5][4]. Users are encouraged to adjust this value based on their specific hardware: - 16 for macOS devices with >16GB of RAM [6]. - 8 for macOS devices with 8-16GB of RAM [6]. - 4 for iOS devices [6]. - 1 for sequential, memory-minimal processing [6].
Citations:
🏁 Script executed:
Repository: kitlangton/Hex
Length of output: 4984
🌐 Web query:
WhisperKit DecodingOptions concurrentWorkerCount source 0 unbounded default 16💡 Result:
In WhisperKit, the
concurrentWorkerCountparameter withinDecodingOptionscontrols the number of concurrent tasks (workers) used for audio processing and batch inference [1][2]. Historically, this value was set to 0, which effectively allowed for an unbounded number of concurrent tasks when using features like VAD (Voice Activity Detection) chunking [3][4]. This behavior could lead to excessive memory consumption and crashes on resource-constrained devices, particularly when processing long audio files [3]. To mitigate these memory issues, the default value was updated to 16 in September 2024 (via PR#205) to provide a balance between throughput and peak memory usage [3][4]. Current implementations typically utilize this default of 16, though it can be adjusted based on the target platform's available memory [5][2]. For instance, on iOS or memory-limited environments, it is often recommended to use a lower value (such as 4), while high-memory macOS environments may support higher values [5][2][6].Citations:
🌐 Web query:
site:github.com/argmaxinc/WhisperKit DecodingOptions concurrentWorkerCount default 0💡 Result:
In the WhisperKit framework, the
concurrentWorkerCountparameter withinDecodingOptionscontrols the number of concurrent tasks (specifically audio chunks) processed during transcription [1][2]. While earlier versions of the framework utilized a default value of 0—which signified that all audio arrays were processed in a single batch (effectively unlimited concurrency relative to the number of input items) [2]—this was later changed to mitigate memory issues during Voice Activity Detection (VAD) processing [3][4]. As of the current implementation, the default value forconcurrentWorkerCountis 16 [3][5]. This value was selected to provide a balance between maintaining high throughput and limiting peak memory consumption, particularly on devices like those running iOS [4]. Users may still manually configure this value to optimize performance based on their specific hardware and input files [4].Citations:
🏁 Script executed:
Repository: kitlangton/Hex
Length of output: 4753
Make sequential transcription explicitly sequential
Current WhisperKit docs indicate
concurrentWorkerCountof0does not force sequential work and newer versions default this to a capped concurrent value. As written, disabling Parallel Mode uses the standard WhisperKittranscribe(...)path with options that may still run concurrently, whileTranscriptionClienttreatsoptions.concurrentWorkerCount > 0as parallel. Use an explicit sequential value/config if the setting is meant to disable parallel chunking, and avoid hardcoding8by deriving the cap from available cores/memory.🤖 Prompt for AI Agents