Skip to content

Commit 1687422

Browse files
committed
style: Added more depth to style of UI. Added Minimum sizes to most components.
fix: Implemented better webscrapping, apis and handling for other subtitle providers fix: Implemented better whisper ai handling, GPU support, and so on. fix: bugs for batch processes with the new workers for subtitles. Note: Whisper AI uses Pytorch which supports GPU usuage for accelerated transcribing. However it currnetly only supports CUDA (NVIDIA), and ROCm (AMD Linux ONLY). Windows AMD for RocM requires preview drivers and only supports very specific graphics series. So support was not implemented for Windows AMD.
1 parent 5c54a1d commit 1687422

28 files changed

Lines changed: 2121 additions & 792 deletions

.github/chatmodes/PlanMode.chatmode.md

Lines changed: 0 additions & 33 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ htmlcov/
3737
nosetests.xml
3838
coverage.xml
3939
*.cover
40+
chatmodes/
4041
.hypothesis/
4142

4243
# Java / Maven

EncodeForge/src/main/java/com/encodeforge/controller/InitializationDialog.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void showAndWait() {
9494
private void startInitialization() {
9595
CompletableFuture.runAsync(() -> {
9696
try {
97-
// Step 1: Check required libraries
97+
// Step 1: Check required libraries (ALWAYS - even if previously initialized)
9898
updateProgress(new ProgressUpdate("detecting", 10,
9999
"Checking Python libraries...", ""));
100100

@@ -112,11 +112,13 @@ private void startInitialization() {
112112
boolean ffmpegInstalled = dependencyManager.checkFFmpeg().get();
113113
appendLog("FFmpeg: " + (ffmpegInstalled ? "✓ Found" : "✗ Not found"));
114114

115-
// Step 3: Install missing dependencies
115+
// Step 3: Install missing libraries (ALWAYS if not all installed)
116+
// This ensures new libraries like beautifulsoup4/lxml get installed
117+
// even if initialization was previously completed
116118
if (!allInstalled) {
117119
updateProgress(new ProgressUpdate("installing", 30,
118120
"Installing required Python libraries...", ""));
119-
appendLog("\nInstalling required Python libraries...");
121+
appendLog("\nInstalling missing Python libraries...");
120122

121123
try {
122124
dependencyManager.installRequiredLibraries(this::updateProgress).get();
@@ -154,8 +156,11 @@ private void startInitialization() {
154156
});
155157
return;
156158
}
159+
} else {
160+
appendLog("\n✓ All required Python libraries are installed");
157161
}
158162

163+
// Step 4: Install FFmpeg if missing
159164
if (!ffmpegInstalled) {
160165
updateProgress(new ProgressUpdate("installing", 60,
161166
"Installing FFmpeg...", ""));

EncodeForge/src/main/java/com/encodeforge/controller/MainController.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,12 @@ private String formatFileNameWithStatus(String fileName) {
493493

494494
switch (status) {
495495
case SEARCHING:
496-
return fileName + " [Searching...]";
496+
// Show progressive count while searching
497+
if (subtitleCount > 0) {
498+
return fileName + " [🔍 Found " + subtitleCount + "...]";
499+
} else {
500+
return fileName + " [🔍 Searching...]";
501+
}
497502
case COMPLETED:
498503
if (subtitleCount > 0) {
499504
return fileName + " [✓ " + subtitleCount + " subs]";
@@ -4973,19 +4978,6 @@ private void searchAndDisplaySubtitles(boolean advancedSearch) {
49734978
// Use batch search API - Python handles parallel searching internally
49744979
new Thread(() -> {
49754980
try {
4976-
// Update settings once
4977-
JsonObject settingsParams = new JsonObject();
4978-
settingsParams.add("settings", settings.toJson());
4979-
4980-
if (processPool != null) {
4981-
processPool.submitQuickTask("update_settings", settingsParams);
4982-
} else if (pythonBridge != null) {
4983-
JsonObject updateSettings = new JsonObject();
4984-
updateSettings.addProperty("action", "update_settings");
4985-
updateSettings.add("settings", settings.toJson());
4986-
pythonBridge.sendCommand(updateSettings);
4987-
}
4988-
49894981
// Track how many files have completed
49904982
final int totalFilesToProcess = queuedFiles.size();
49914983
final java.util.concurrent.atomic.AtomicInteger filesCompleted = new java.util.concurrent.atomic.AtomicInteger(0);
@@ -5141,6 +5133,10 @@ private void processFileSearchResponse(String fileName, JsonObject response,
51415133

51425134
if (isComplete) {
51435135
log("[" + fileName + "] ✅ " + provider + " - search complete");
5136+
// Update status label to show completed provider
5137+
if (subtitleProgressStatusLabel != null) {
5138+
subtitleProgressStatusLabel.setText("Completed " + provider);
5139+
}
51445140
// If complete message has subtitles, process them
51455141
if (!hasSubtitles) {
51465142
return;
@@ -5149,6 +5145,10 @@ private void processFileSearchResponse(String fileName, JsonObject response,
51495145
response.getAsJsonArray("subtitles").size(), fileName);
51505146
} else {
51515147
log("[" + fileName + "] 🔍 Searching " + provider + "...");
5148+
// Update status label to show current provider being searched
5149+
if (subtitleProgressStatusLabel != null) {
5150+
subtitleProgressStatusLabel.setText("Searching " + provider + "...");
5151+
}
51525152
return; // Return early for non-complete progress updates
51535153
}
51545154
}
@@ -5157,7 +5157,8 @@ private void processFileSearchResponse(String fileName, JsonObject response,
51575157
if (response.has("status")) {
51585158
String status = response.get("status").getAsString();
51595159

5160-
if ("success".equals(status) && response.has("subtitles")) {
5160+
// Handle both "success" (old API) and "file_complete" (new batch API)
5161+
if (("success".equals(status) || "file_complete".equals(status)) && response.has("subtitles")) {
51615162
JsonArray subtitles = response.getAsJsonArray("subtitles");
51625163

51635164
// Add subtitles to this file's list
@@ -5201,6 +5202,9 @@ private void processFileSearchResponse(String fileName, JsonObject response,
52015202
}
52025203
}
52035204

5205+
// ALWAYS update the dropdown when we receive subtitles (progressive update)
5206+
updateSubtitleFileList();
5207+
52045208
// Check if this is the final result for this file
52055209
// Note: "file_complete" means this file is done, but stream continues
52065210
// "complete" means the entire batch is done

EncodeForge/src/main/java/com/encodeforge/controller/WhisperSetupDialog.java

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -255,17 +255,22 @@ private void startInstallation() {
255255
updateInstallProgress(new ProgressUpdate("installing", 10,
256256
"Installing Whisper AI (this may take several minutes)...", ""));
257257

258-
// Specify only package names without version constraints
259-
// Let pip resolve the best compatible versions for the Python environment
260-
List<String> packages = Arrays.asList(
261-
"openai-whisper",
262-
"torch"
263-
);
264-
265-
dependencyManager.installOptionalLibraries(packages, this::updateInstallProgress).get();
258+
// Install openai-whisper first (without torch to avoid CPU version)
259+
List<String> whisperPackage = Arrays.asList("openai-whisper");
260+
dependencyManager.installOptionalLibraries(whisperPackage, this::updateInstallProgress).get();
266261

267262
appendLog("✓ Whisper AI packages installed successfully");
268263

264+
// Step 1.5: Install PyTorch with ROCm support
265+
appendLog("\nDetecting GPU and installing PyTorch...");
266+
updateInstallProgress(new ProgressUpdate("installing", 40,
267+
"Installing PyTorch with GPU support...", ""));
268+
269+
// Install torch with ROCm support
270+
dependencyManager.installTorchWithGPUSupport(this::updateInstallProgress).get();
271+
272+
appendLog("✓ PyTorch installed with GPU support");
273+
269274
// Step 2: Download the selected model via process pool (with streaming progress)
270275
updateInstallProgress(new ProgressUpdate("downloading", 70,
271276
"Downloading " + selectedModel + " model...", ""));
@@ -279,39 +284,52 @@ private void startInstallation() {
279284
params.addProperty("model", selectedModel);
280285

281286
processPool.submitStreamingTask("download_whisper_model", params, response -> {
282-
Platform.runLater(() -> {
287+
try {
283288
if (response == null) {
284289
logger.warn("Received null response during model download");
285290
return;
286291
}
287292

288-
if (response.has("type") && "progress".equals(response.get("type").getAsString())) {
289-
// Progress update
290-
int progress = response.has("progress") ? response.get("progress").getAsInt() : 0;
291-
String message = response.has("message") ? response.get("message").getAsString() : "Downloading...";
292-
293-
// Update UI with progress (70-100 range since we're at 70% already)
294-
int totalProgress = 70 + (progress * 30 / 100);
295-
updateInstallProgress(new ProgressUpdate("downloading", totalProgress, message, ""));
296-
appendLog("Progress: " + progress + "% - " + message);
297-
} else {
298-
// Final response
299-
String status = response.has("status") ? response.get("status").getAsString() : "unknown";
300-
String message = response.has("message") ? response.get("message").getAsString() : "";
301-
302-
if ("success".equals(status) || "complete".equals(status)) {
303-
appendLog("✓ Model downloaded successfully");
304-
logger.info("Download completed successfully, completing future");
305-
downloadFuture.complete(null);
306-
} else if ("error".equals(status)) {
307-
appendLog("❌ Download failed: " + message);
308-
logger.error("Download failed with error: {}", message);
309-
downloadFuture.completeExceptionally(new Exception(message));
310-
} else {
311-
logger.debug("Received status: {} - {}", status, message);
293+
// Log raw response for debugging
294+
logger.debug("Model download response: {}", response.toString());
295+
296+
Platform.runLater(() -> {
297+
try {
298+
if (response.has("type") && "progress".equals(response.get("type").getAsString())) {
299+
// Progress update
300+
int progress = response.has("progress") ? response.get("progress").getAsInt() : 0;
301+
String message = response.has("message") ? response.get("message").getAsString() : "Downloading...";
302+
303+
// Update UI with progress (70-100 range since we're at 70% already)
304+
int totalProgress = 70 + (progress * 30 / 100);
305+
updateInstallProgress(new ProgressUpdate("downloading", totalProgress, message, ""));
306+
appendLog("Progress: " + progress + "% - " + message);
307+
} else {
308+
// Final response or other status
309+
String status = response.has("status") ? response.get("status").getAsString() : "unknown";
310+
String message = response.has("message") ? response.get("message").getAsString() : "";
311+
312+
logger.info("Received final response - status: {}, message: {}", status, message);
313+
314+
if ("success".equals(status) || "complete".equals(status)) {
315+
appendLog("✓ Model downloaded and verified successfully");
316+
logger.info("Download completed successfully, completing future");
317+
downloadFuture.complete(null);
318+
} else if ("error".equals(status)) {
319+
appendLog("❌ Download failed: " + message);
320+
logger.error("Download failed with error: {}", message);
321+
downloadFuture.completeExceptionally(new Exception(message));
322+
} else {
323+
logger.debug("Received intermediate status: {} - {}", status, message);
324+
}
325+
}
326+
} catch (Exception e) {
327+
logger.error("Error in Platform.runLater callback", e);
312328
}
313-
}
314-
});
329+
});
330+
} catch (Exception e) {
331+
logger.error("Error in streaming callback", e);
332+
}
315333
});
316334

317335
// Wait for download to complete

0 commit comments

Comments
 (0)