Compare commits

..

3 Commits

Author SHA1 Message Date
MikeHughes-BIN b6276b005e Removed Parakeet again as it requires PyTorch which is too large for this project 2026-01-18 19:13:18 +01:00
MikeHughes-BIN 8f2024df14 Refactor HTML structure for improved readability and maintainability 2026-01-18 19:12:04 +01:00
MikeHughes-BIN 0f548b3012 Add function to send speaker packages and handle errors 2026-01-18 19:05:55 +01:00
5 changed files with 350 additions and 370 deletions
+166 -81
View File
@@ -1,16 +1,17 @@
<!DOCTYPE html> <!doctype html>
<html lang="de"> <html lang="de">
<head>
<head> <meta charset="UTF-8" />
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title id="title">Video to document</title> <title id="title">Video to document</title>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/themes/light.css"> <link
</head> rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/themes/light.css"
<body> />
</head>
<body>
<div id="h1-wrapper"> <div id="h1-wrapper">
<section class="p-menu1"> <section class="p-menu1">
<nav id="navbar" class="navigation" role="navigation"> <nav id="navbar" class="navigation" role="navigation">
@@ -22,7 +23,9 @@
</label> </label>
<nav class="menu1"> <nav class="menu1">
<button id="customDocBtn" onclick="showCD()">Manage document types</button> <button id="customDocBtn" onclick="showCD()">
Manage document types
</button>
<a href="help_page.html" class="li1">Help</a> <a href="help_page.html" class="li1">Help</a>
</nav> </nav>
</nav> </nav>
@@ -33,7 +36,6 @@
<div class="gui-language"> <div class="gui-language">
<select name="language_option" id="language_option"></select> <select name="language_option" id="language_option"></select>
</div> </div>
</div> </div>
<div class="step-nav"> <div class="step-nav">
@@ -50,24 +52,34 @@
<!-- Visible middle part--> <!-- Visible middle part-->
<div class="mitte" id="mitte"> <div class="mitte" id="mitte">
<!--Costum document section--> <!--Costum document section-->
<div class="container" id="cdContainer" style="display:none;"> <div class="container" id="cdContainer" style="display: none">
<h1 id="cd_h1">Manage document types</h1> <h1 id="cd_h1">Manage document types</h1>
<label for="existingDocs" id="cd_existingDocs">Select existing documents (optional):</label> <label for="existingDocs" id="cd_existingDocs"
>Select existing documents (optional):</label
>
<!--Drop Down--> <!--Drop Down-->
<select name="existingDocs" id="existingDocs"> <select name="existingDocs" id="existingDocs">
<option value="newDoc" id="newDoc">-- Create new document --</option> <option value="newDoc" id="newDoc">
-- Create new document --
</option>
</select> </select>
<div id="docNameWrapper"> <div id="docNameWrapper">
<label for="docName" id="cd_docName">Document name:</label> <label for="docName" id="cd_docName">Document name:</label>
<input type="text" id="docName" placeholder="Enter the document name here"> <input
type="text"
id="docName"
placeholder="Enter the document name here"
/>
</div> </div>
<label for="prompt" id="cd_promt">Your prompt:</label> <label for="prompt" id="cd_promt">Your prompt:</label>
<textarea id="prompt" placeholder="Type the prompt for your document here..."></textarea> <textarea
id="prompt"
placeholder="Type the prompt for your document here..."
></textarea>
<div class="buttons"> <div class="buttons">
<button id="goBackBtn">Return</button> <button id="goBackBtn">Return</button>
@@ -83,118 +95,175 @@
<h2 class="h2">Upload your video here:</h2> <h2 class="h2">Upload your video here:</h2>
<div class="upload-container" id="uploadContainer"> <div class="upload-container" id="uploadContainer">
<p id="p1">Drag and drop video file</p> <p id="p1">Drag and drop video file</p>
<video id="previewThumbnail" autoplay="false"> <video id="previewThumbnail" autoplay="false"></video>
</video>
<div class="file-name" id="fileName">No video chosen</div> <div class="file-name" id="fileName">No video chosen</div>
<div id="thumbnailContainer"> <div id="thumbnailContainer">
<img id="thumbnailImage" style="display:none;"> <img id="thumbnailImage" style="display: none" />
</div> </div>
<button class="custom-btn" id="manualUploadBtn">Search video</button> <button class="custom-btn" id="manualUploadBtn">
<input type="file" id="videoUpload" accept="video/*"> Search video
</button>
<input type="file" id="videoUpload" accept="video/*" />
</div> </div>
</div> </div>
<!-- Here starts code from step 2--> <!-- Here starts code from step 2-->
<div class="step" id="step2" style="display:none;"> <div class="step" id="step2" style="display: none">
<h2 class="h2">Choose your preferences:</h2> <h2 class="h2">Choose your preferences:</h2>
<div class="step2-form"> <div class="step2-form">
<div class="KI-wrapper">
<div class="step2-row"> <label id="labelKI">Select ki:</label>
<label>Select ki:</label> <select name="ai_type" id="ai_type"></select>
<select id="ai_type"></select>
</div> </div>
<div class="step2-row"> <div class="transcript-wrap">
<label>Select transcription:</label> <label id="labelTranscription">Select transcription:</label>
<select id="transkript_type"></select> <select name="transkript_type" id="transkript_type"></select>
</div> </div>
<div class="step2-row"> <div class="type-wrapper">
<label>Select type:</label> <label id="labelType">Select type:</label>
<select id="output_type"> <select name="output_type" id="output_type">
<option>.pdf</option> <option value="pdf">.pdf</option>
<option>.docx</option> <option value="word">.word</option>
<option>.txt</option> <option value="txt">.txt</option>
</select> </select>
</div> </div>
<div class="step2-row"> <div class="language-wrapper">
<label>Select language:</label> <label id="labelLanguage">Select language:</label>
<select id="document_language_option"></select>
</div>
<select
name="document_language_option"
id="document_language_option"
></select>
</div>
</div> </div>
</div> </div>
<!-- Here starts code from step 3--> <!-- Here starts code from step 3-->
<!-- Hover Effekt für Dokumentenvorschau, Fragezeichen hinter Text, drüber hoven zeigt Beispieldokument --> <!-- Hover Effekt für Dokumentenvorschau, Fragezeichen hinter Text, drüber hoven zeigt Beispieldokument -->
<div class="step" id="step3" style="display:none;"> <div class="step" id="step3" style="display: none">
<div class="checkbox-group"> <div class="checkbox-group">
<h2 class="h2">Choose prefered document style:</h2> <h2 class="h2">Choose prefered document style:</h2>
<div class="checkbox-container"> <div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormat" value="followup-report"> <input
type="checkbox"
name="docFormat"
id="docFormat"
value="followup-report"
/>
<label id="label_format" for="docFormat">Follow-up Report</label> <label id="label_format" for="docFormat">Follow-up Report</label>
<div class="figure1"> <div class="figure1">
<img class="img-icon" src="icons/question-mark-button-icon--free-clip-art-30.png"> <img
<img class="img-hover1" src="flags/germany-flag-png-large.jpg"> class="img-icon"
src="icons/question-mark-button-icon--free-clip-art-30.png"
/>
<img
class="img-hover1"
src="flags/germany-flag-png-large.jpg"
/>
</div> </div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary1" value="agenda"> <input
type="checkbox"
name="docFormat"
id="docFormatSummary1"
value="agenda"
/>
<label id="label_summary" for="docFormatSummary">Agenda</label> <label id="label_summary" for="docFormatSummary">Agenda</label>
<div class="figure2"> <div class="figure2">
<img class="img-icon" src="icons/question-mark-button-icon--free-clip-art-30.png"> <img
<img class="img-hover2" src="flags/india-flag-png-large.png"> class="img-icon"
src="icons/question-mark-button-icon--free-clip-art-30.png"
/>
<img class="img-hover2" src="flags/india-flag-png-large.png" />
</div> </div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary2" value="result-protocol"> <input
<label id="label_summary" for="docFormatSummary">Resultprotocol</label> type="checkbox"
name="docFormat"
id="docFormatSummary2"
value="result-protocol"
/>
<label id="label_summary" for="docFormatSummary"
>Resultprotocol</label
>
<div class="figure3"> <div class="figure3">
<img class="img-icon" src="icons/question-mark-button-icon--free-clip-art-30.png"> <img
<img class="img-hover3" src="flags/united-kingdom-flag-png-large.jpg"> class="img-icon"
src="icons/question-mark-button-icon--free-clip-art-30.png"
/>
<img
class="img-hover3"
src="flags/united-kingdom-flag-png-large.jpg"
/>
</div> </div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary3" value="sprint-planning"> <input
<label id="label_summary" for="docFormatSummary">Sprint Planning Note</label> type="checkbox"
name="docFormat"
id="docFormatSummary3"
value="sprint-planning"
/>
<label id="label_summary" for="docFormatSummary"
>Sprint Planning Note</label
>
<div class="figure4"> <div class="figure4">
<img class="img-icon" src="icons/question-mark-button-icon--free-clip-art-30.png"> <img
<img class="img-hover4" src="flags/germany-flag-png-large.jpg"> class="img-icon"
src="icons/question-mark-button-icon--free-clip-art-30.png"
/>
<img
class="img-hover4"
src="flags/germany-flag-png-large.jpg"
/>
</div> </div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatCustom" value="custom"> <input
<select name="customDocumentTypes" id="customDocumentTypes"> type="checkbox"
</select> name="docFormat"
id="docFormatCustom"
value="custom"
/>
<select
name="customDocumentTypes"
id="customDocumentTypes"
></select>
</div> </div>
</div> </div>
</div> </div>
<!-- Here starts code from step 4--> <!-- Here starts code from step 4-->
<div class="step" id="step4" style="display:none;"> <div class="step" id="step4" style="display: none">
<h2 class="h2">Click to submit:</h2> <h2 class="h2">Click to submit:</h2>
<button class="submit-btn" id="submitButton" onclick="checkBoxes()" disabled>Submit</button> <button
class="submit-btn"
id="submitButton"
onclick="checkBoxes()"
disabled
>
Submit
</button>
<div class="testy" id="testy"> <div class="testy" id="testy">
<div class="box2" id="box1"> <div class="box2" id="box1"></div>
</div>
<p id="box1_p1">---Starting---</p> <p id="box1_p1">---Starting---</p>
<div class="box2" id="box2"> <div class="box2" id="box2"></div>
</div>
<p id="box2_p2">---Transkribing---</p> <p id="box2_p2">---Transkribing---</p>
<div class="box2" id="box3"> <div class="box2" id="box3"></div>
</div>
<p id="box3_p3">---Document creation---</p> <p id="box3_p3">---Document creation---</p>
<div class="box2" id="box4"> <div class="box2" id="box4"></div>
</div>
</div> </div>
</div> </div>
<!-- Here starts code from step 5--> <!-- Here starts code from step 5-->
<div class="step" id="step5" style="display:none;"> <div class="step" id="step5" style="display: none">
<h2 class="h2">Change names of the speakers:</h2> <h2 class="h2">Change names of the speakers:</h2>
<div class="speaker-container"> <div class="speaker-container">
@@ -202,7 +271,9 @@
<tbody> <tbody>
<tr> <tr>
<td class="label-cell"> <td class="label-cell">
<label id="labelSpeaker" for="cur_speaker">Select Speaker:</label> <label id="labelSpeaker" for="cur_speaker"
>Select Speaker:</label
>
</td> </td>
<td class="input-cell"> <td class="input-cell">
<select name="cur_speaker" id="cur_speaker"></select> <select name="cur_speaker" id="cur_speaker"></select>
@@ -220,36 +291,50 @@
</tr> </tr>
<tr> <tr>
<td class="label-cell"> <td class="label-cell">
<label id="labelSpeakerWriter" for="newSpeaker">New Name:</label> <label id="labelSpeakerWriter" for="newSpeaker"
>New Name:</label
>
</td> </td>
<td class="input-cell"> <td class="input-cell">
<input type="text" id="newSpeaker" placeholder="Enter new speaker name"> <input
type="text"
id="newSpeaker"
placeholder="Enter new speaker name"
/>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="speaker-button-group"> <div class="speaker-button-group">
<button id="speakerLocker" onclick="rewriteSpeakerName()">Rename Speaker</button> <button id="speakerLocker" onclick="rewriteSpeakerName()">
<button id="speakerResender" onclick="sendSpeakerPackages()">Rewrite Document</button> Rename Speaker
</button>
<button id="speakerResender" onclick="sendSpeakerPackages()">
Rewrite Document
</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Here starts code from step 6--> <!-- Here starts code from step 6-->
<div class="step" id="step6" style="display:none;"> <div class="step" id="step6" style="display: none">
<h2 class="h2">Click to download your document:</h2> <h2 class="h2">Click to download your document:</h2>
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button> <button
class="download-btn"
id="downloadButton"
onclick="fileDownload()"
>
Download
</button>
</div> </div>
</div> </div>
<button id="nextBtn" class="navBtn">&rarr;</button> <button id="nextBtn" class="navBtn">&rarr;</button>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/lc_select.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/lc_select.min.js"></script>
<script src="languages.js"></script> <script src="languages.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
<script src="./renderer.js"></script> <script src="./renderer.js"></script>
</body> </body>
</html> </html>
+10
View File
@@ -500,3 +500,13 @@ function reloadDocuments() {
}); });
}); });
} }
function sendSpeakerPackages() {
try {
window.submitSpeaker.speaker_submit(speakerAudios);
} catch (error) {
console.log(error);
}
}
window.sendSpeakerPackages = sendSpeakerPackages;
+10
View File
@@ -316,6 +316,16 @@ electron.ipcMain.on("file_download", async (event) => {
} }
}); });
electron.ipcMain.on("file_download", async () => {
await mapFunctions
.get("htmlDocumentConverter")
.convert({
inputPath: globalFinalHtmlPath,
format: globalArgs.document.outputType,
showDialog: true,
});
});
electron.ipcMain.on("speaker_submit", async (event, args) => { electron.ipcMain.on("speaker_submit", async (event, args) => {
console.log("\n\n\nJa also hier kam was an \n\n\n"); console.log("\n\n\nJa also hier kam was an \n\n\n");
console.log(args); console.log(args);
@@ -1,54 +0,0 @@
// -----------------------------------------------------------
// Parakeet (Step 3A: spawn Python minimal integration)
// -----------------------------------------------------------
const fs = require("fs");
const path = require("path");
const { spawn } = require("child_process");
module.exports = {
name: "parakeet",
type: "transcription",
displayname: "NVIDIA Parakeet",
async function(audioFilePath) {
console.log("🦜 [Parakeet] Starting test integration (spawn only)...");
console.log("🦜 Input audio:", audioFilePath);
// Check audio exists
if (!fs.existsSync(audioFilePath)) {
throw new Error("Audio file does not exist: " + audioFilePath);
}
// Output path in storage/transcripts
const sessionId = path.basename(audioFilePath).replace(/\.[^.]+$/, "");
const outputDir = path.join(__dirname, "../../../storage/transcripts");
fs.mkdirSync(outputDir, { recursive: true });
const outputPath = path.join(outputDir, `${sessionId}.json`);
// -------------------------------------------------------
// SPAWN PYTHON SCRIPT (step 3A — dummy script)
// -------------------------------------------------------
return new Promise((resolve, reject) => {
const python310 = "C:\\Users\\smith\\AppData\\Local\\Programs\\Python\\Python310\\python.exe";
const py = spawn(python310, [
path.join(__dirname, "parakeet_transcribe.py"),
audioFilePath,
outputPath
]);
py.stdout.on("data", data => console.log("🦜 [Python]", data.toString().trim()));
py.stderr.on("data", data => console.error("🦜 [Python ERR]", data.toString().trim()));
py.on("close", code => {
if (code === 0) {
console.log("🦜 [Parakeet] Done (spawn test). Output:", outputPath);
resolve(outputPath);
} else {
reject(new Error("Python script failed with exit code " + code));
}
});
});
}
};
@@ -1,71 +0,0 @@
# -----------------------------------------------------------
# Parakeet Real Transcriber (NVIDIA NeMo + PyTorch GPU)
# -----------------------------------------------------------
import sys
import json
import soundfile as sf
import torch
from nemo.collections.asr.models import ASRModel
# Args:
# sys.argv[1] = input audio path
# sys.argv[2] = output JSON path
audio_path = sys.argv[1]
output_path = sys.argv[2]
print("🔥 Starting Parakeet model...")
device = "cuda" if torch.cuda.is_available() else "cpu"
print("🔥 Using device:", device)
# -----------------------------------------------------------
# Load Parakeet model (NVIDIA pretrained ASR)
# -----------------------------------------------------------
model = ASRModel.from_pretrained(model_name="nvidia/parakeet-ctc-0.6b")
model = model.to(device)
model.eval()
# -----------------------------------------------------------
# Load audio
# -----------------------------------------------------------
print("🎧 Loading audio:", audio_path)
audio, sr = sf.read(audio_path)
# model expects mono float32
if len(audio.shape) > 1:
audio = audio.mean(axis=1)
audio = audio.astype("float32")
# -----------------------------------------------------------
# Run inference
# -----------------------------------------------------------
print("🧠 Running inference...")
with torch.no_grad():
hyp = model.transcribe([audio])[0]
# Extract only the text
if hasattr(hyp, "text"):
transcript = hyp.text
else:
# fallback: convert to string (rare)
transcript = str(hyp)
print("📄 Transcript:", transcript)
# -----------------------------------------------------------
# Save JSON format compatible with V2D pipeline
# -----------------------------------------------------------
result = {
"id": output_path.split("/")[-1].replace(".json", ""),
"tool": "nemo_parakeet",
"status": "completed",
"text": transcript,
"words": [] # Parakeet XS doesnt return word timestamps
}
with open(output_path, "w", encoding="utf-8") as f:
json.dump(result, f, indent=2, ensure_ascii=False)
print("✔ JSON saved at:", output_path)