mirror of
https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
synced 2026-06-15 18:01:52 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bd5ae52c6 |
+2
-16
@@ -963,23 +963,9 @@ app.*.symbols
|
|||||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||||
!/dev/ci/**/Gemfile.lock
|
!/dev/ci/**/Gemfile.lock
|
||||||
|
|
||||||
# Storage files
|
#Storage files
|
||||||
storage/documents/*
|
storage/
|
||||||
storage/transcriptionSummaries/*
|
|
||||||
storage/transcripts/*
|
|
||||||
storage/video/*
|
|
||||||
# The inverse for the .gitkeep files, to make sure the folders are there but not the local files
|
|
||||||
!storage/documents/.gitkeep
|
|
||||||
!storage/transcriptionSummaries/.gitkeep
|
|
||||||
!storage/transcripts/.gitkeep
|
|
||||||
!storage/video/.gitkeep
|
|
||||||
|
|
||||||
*.mp4
|
*.mp4
|
||||||
*.webm
|
|
||||||
*.mp3
|
|
||||||
*.mov
|
|
||||||
*.wav
|
*.wav
|
||||||
*.flac
|
*.flac
|
||||||
|
|
||||||
|
|
||||||
!testvideo.mp4
|
|
||||||
|
|||||||
+25
-19
@@ -1,27 +1,33 @@
|
|||||||
image: node:latest
|
workflow:
|
||||||
|
rules:
|
||||||
|
# Run the pipeline for merge requests or when committing to a branch
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
|
image: python:3.14.0
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
# - install
|
- setup
|
||||||
- test
|
- test
|
||||||
|
|
||||||
# job-install:
|
setup_environment:
|
||||||
# stage: install
|
stage: setup
|
||||||
# script:
|
script:
|
||||||
# - npm install
|
- pip install --upgrade pip
|
||||||
# artifacts:
|
- pip install -r requirements.txt
|
||||||
# untracked: false
|
- echo "Dependencies installed successfully."
|
||||||
# when: on_success
|
|
||||||
# access: all
|
|
||||||
# expire_in: "30 days"
|
|
||||||
# paths:
|
|
||||||
# - node_modules
|
|
||||||
|
|
||||||
|
only:
|
||||||
|
- main
|
||||||
|
- feature/ci-pipeline-s1-09a-1 # You can add more branches if needed
|
||||||
|
|
||||||
|
test_app:
|
||||||
job-test:
|
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- npm install
|
- echo "Running V2D Framework basic test..."
|
||||||
- echo "ASSEMBLYAI_API_KEY=$apikey_assembly" > .env
|
- python -m unittest discover || echo "No tests found."
|
||||||
- echo "GOOGLE_API_KEY=$apikey_gemini" >> .env
|
|
||||||
- npm test
|
only:
|
||||||
|
- main
|
||||||
|
- feature/ci-pipeline-s1-09a-1
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Custom Document</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background: #f0f2f5;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: white;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 50px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
|
||||||
|
width: 90%;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 15px;
|
||||||
|
display: block;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"], textarea, select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
height: 120px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.2s;
|
||||||
|
background-color: #007BFF;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
.buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.buttons button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#result {
|
||||||
|
margin-top: 20px;
|
||||||
|
color: #333;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Custom Document Generator</h1>
|
||||||
|
|
||||||
|
<label for="docName">Dokumentname:</label>
|
||||||
|
<input type="text" id="docName" placeholder="Gib hier den Dokumentnamen ein">
|
||||||
|
|
||||||
|
<label for="existingDocs">Vorhandene Dokumente auswählen (optional):</label>
|
||||||
|
<select id="existingDocs">
|
||||||
|
<option value="">-- Neues Dokument erstellen --</option>
|
||||||
|
<option value="meeting_report_001">Meeting Report 001</option>
|
||||||
|
<option value="summary_01">Summary 01</option>
|
||||||
|
<option value="project_plan_A">Project Plan A</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label for="prompt">Dein Prompt:</label>
|
||||||
|
<textarea id="prompt" placeholder="Schreibe hier den Prompt für dein Dokument..."></textarea>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<button id="goBackBtn">Abbrechen</button>
|
||||||
|
<button id="generateBtn">Dokument speichern</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="result"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const goBackBtn = document.getElementById("goBackBtn");
|
||||||
|
const generateBtn = document.getElementById("generateBtn");
|
||||||
|
const existingDocs = document.getElementById("existingDocs");
|
||||||
|
const docNameInput = document.getElementById("docName");
|
||||||
|
const promptInput = document.getElementById("prompt");
|
||||||
|
const resultDiv = document.getElementById("result");
|
||||||
|
|
||||||
|
// Zurück zur Haupt-GUI
|
||||||
|
goBackBtn.addEventListener("click", () => {
|
||||||
|
window.electronAPI.goBackToMain();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Generiere Dokument
|
||||||
|
generateBtn.addEventListener("click", () => {
|
||||||
|
const prompt = promptInput.value.trim();
|
||||||
|
let docName = docNameInput.value.trim();
|
||||||
|
const selectedExisting = existingDocs.value;
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
alert("Bitte gib einen Prompt ein!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn ein vorhandenes Dokument ausgewählt wurde, hängt der Prompt daran
|
||||||
|
if (selectedExisting) {
|
||||||
|
docName = selectedExisting; // prompt wird an vorhandenes Dokument angehängt
|
||||||
|
} else if (!docName) {
|
||||||
|
alert("Bitte gib einen Dokumentnamen ein, wenn du ein neues Dokument erstellen möchtest!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demo-Ausgabe im Result-Div
|
||||||
|
resultDiv.innerHTML = `<strong>Dokumentname:</strong> ${docName}<br><strong>Prompt:</strong> ${prompt}`;
|
||||||
|
|
||||||
|
// Hier kannst du den Prompt an dein LLM oder Module-Handler senden
|
||||||
|
// z.B. window.submit.submit({documentName: docName, prompt: prompt})
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+51
-142
@@ -7,154 +7,63 @@
|
|||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="h1-wrapper">
|
|
||||||
<section class="p-menu1">
|
|
||||||
<nav id="navbar" class="navigation" role="navigation">
|
|
||||||
<input id="toggle1" type="checkbox" />
|
|
||||||
<label class="hamburger1" for="toggle1">
|
|
||||||
<div class="top"></div>
|
|
||||||
<div class="meat"></div>
|
|
||||||
<div class="bottom"></div>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<nav class="menu1">
|
|
||||||
<li class="li1">Help</li>
|
|
||||||
<li class="li1">Language</li>
|
|
||||||
</nav>
|
|
||||||
</nav>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<h1 id="h1">Video to document</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step-nav">
|
|
||||||
<div class="step-item active" data-step="1">1. Step</div>
|
|
||||||
<div class="step-item" data-step="2">2. Step</div>
|
|
||||||
<div class="step-item" data-step="3">3. Step</div>
|
|
||||||
<div class="step-item" data-step="4">4. Step</div>
|
|
||||||
<div class="step-item" data-step="5">5. Step</div>
|
|
||||||
<div class="step-item" data-step="6">6. Step</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="middleContainerWrapper" class="middle-container-wrapper">
|
<div class="mitte" id="mitte">
|
||||||
<button id="prevBtn" class="navBtn" disabled>←</button>
|
<div class="labelDiv" id="labelDiv">
|
||||||
|
<label id="labelKI">Select ki:</label>
|
||||||
<div class="mitte" id="mitte">
|
<label id="labelTranscription">Select transcription:</label>
|
||||||
|
<label id="labelLanguage">Select language:</label>
|
||||||
<div class="step" id="step1">
|
<img id="labelLanguageFlag" src="flags/united-kingdom-flag-png-large.jpg" width="20" height="10" >
|
||||||
<div class="upload-container" id="uploadContainer">
|
</div>
|
||||||
<p id="p1">Drag and drop video file</p>
|
<div class="dropdownMenus" id="dropdownMenus">
|
||||||
<video id="previewThumbnail" autoplay="false">
|
<select name="ai_type" id="ai_type">
|
||||||
</video>
|
</select>
|
||||||
<div class="file-name" id="fileName">No video chosen</div>
|
<select name="transkript_type" id="transkript_type">
|
||||||
<div id="thumbnailContainer">
|
</select>
|
||||||
<img id="thumbnailImage" style="display:none;">
|
<select name="output_type" id="output_type">
|
||||||
</div>
|
<option value="flac">flac</option>
|
||||||
<button class="custom-btn" id="manualUploadBtn">Search video</button>
|
<option value="mp3">mp3</option>
|
||||||
<input type="file" id="videoUpload" accept="video/*">
|
<option value="wav">wav</option>
|
||||||
</div>
|
</select>
|
||||||
</div>
|
<select name="language_option" id="language_option">
|
||||||
|
</select>
|
||||||
<div class="step" id="step2" style="display:none;">
|
|
||||||
<div class="labelDiv" id="labelDiv">
|
|
||||||
<label id="labelKI">Select ki:</label>
|
|
||||||
<label id="labelTranscription">Select transcription:</label>
|
|
||||||
<label id="labelType">Select type:</label>
|
|
||||||
<label id="labelLanguage">Select language:</label>
|
|
||||||
<img id="labelLanguageFlag" src="flags/united-kingdom-flag-png-large.jpg" width="20" height="10" >
|
|
||||||
</div>
|
|
||||||
<div class="dropdownMenus" id="dropdownMenus">
|
|
||||||
<select name="ai_type" id="ai_type">
|
|
||||||
</select>
|
|
||||||
<select name="transkript_type" id="transkript_type">
|
|
||||||
</select>
|
|
||||||
<select name="output_type" id="output_type">
|
|
||||||
<option value="pdf">.pdf</option>
|
|
||||||
<option value="word">.word</option>
|
|
||||||
<option value="txt">.txt</option>
|
|
||||||
</select>
|
|
||||||
<select name="language_option" id="language_option">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step" id="step3" style="display:none;">
|
|
||||||
<div class="checkbox-group">
|
|
||||||
<label id="checkbox-label" for="checkbox-group">Choose prefered document style:</label>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<input type="checkbox" name ="docFormat" id="docFormat" value="Meeting report">
|
|
||||||
<label id="label_format" for="docFormat">Follow-up Report</label>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<input type="checkbox" name="docFormat" id="docFormatSummary1" value="Summary with timestamps">
|
|
||||||
<label id="label_summary" for="docFormatSummary">Agenda</label>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<input type="checkbox" name="docFormat" id="docFormatSummary2" value="Summary with timestamps">
|
|
||||||
<label id="label_summary" for="docFormatSummary">Resultprotocol</label>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<input type="checkbox" name="docFormat" id="docFormatSummary3" value="Summary with timestamps">
|
|
||||||
<label id="label_summary" for="docFormatSummary">Sprint Planning Note</label>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<input type="checkbox" name="docFormat" id="docFormatCustom" value="Summary with timestamps">
|
|
||||||
<select name="ai_type" id="ai_type">
|
|
||||||
<option>nichts</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step" id="step4" style="display:none;">
|
|
||||||
<button class="submit-btn" id="submitButton" onclick="checkBoxes()" disabled>Submit</button>
|
|
||||||
|
|
||||||
<div class="testy" id="testy">
|
|
||||||
<div class="box2" id="box1">
|
|
||||||
</div>
|
|
||||||
<p>---Starting---</p>
|
|
||||||
<div class="box2" id="box2">
|
|
||||||
</div>
|
|
||||||
<p>---Transkribing---</p>
|
|
||||||
<div class="box2" id="box3">
|
|
||||||
</div>
|
|
||||||
<p>---Document creation---</p>
|
|
||||||
<div class="box2" id="box4">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step" id="step5" style="display:none;">
|
|
||||||
<div class="speakerView" id="speakerView">
|
|
||||||
<label id="labelSpeaker">Select Speaker:</label>
|
|
||||||
<select name="cur_speaker" id="cur_speaker">
|
|
||||||
<options>Stefan</options>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="speakerAudio" id="speakerAutio">
|
|
||||||
<label id="labelSpeakerAudio">Selected Speaker</label>
|
|
||||||
<audio controls id="speakerAudioViewer">
|
|
||||||
Currently there is no audio file here.
|
|
||||||
</audio>
|
|
||||||
</div>
|
|
||||||
<div class="speakerWrite" id="speakerWrite">
|
|
||||||
<label id="labelSpeakerWriter">Write name:</label>
|
|
||||||
<input type="text" id="newSpeaker">
|
|
||||||
</div>
|
|
||||||
<button id="speakerLocker" onclick="rewriteSpeakerName()">Rename Speaker</button>
|
|
||||||
<button id="speakerResender" onclick="sendSpeakerPackages()">Rewrite document</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step" id="step6" style="display:none;">
|
|
||||||
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id ="nextBtn" class="navBtn">→</button>
|
<h1 id="h1">Video to document</h1>
|
||||||
|
|
||||||
|
<div class="upload-container" id="uploadContainer">
|
||||||
|
<p id="p1">Drag and drop video file</p>
|
||||||
|
<video id="previewThumbnail" autoplay="false">
|
||||||
|
</video>
|
||||||
|
<div class="file-name" id="fileName">No video chosen</div>
|
||||||
|
<div id="thumbnailContainer">
|
||||||
|
<img id="thumbnailImage" style="display:none;">
|
||||||
|
</div>
|
||||||
|
<button class="custom-btn" id="manualUploadBtn">Search video</button>
|
||||||
|
<input type="file" id="videoUpload" accept="video/*">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkbox-group">
|
||||||
|
<label id="checkbox_group" for="checkbox-group">Choose prefered document style:</label>
|
||||||
|
<div class="checkbox-container">
|
||||||
|
<input type="checkbox" name ="docFormat" id="docFormat" value="Meeting report">
|
||||||
|
<label id="label_format" for="docFormat">Meeting report</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkbox-container">
|
||||||
|
<input type="checkbox" name="docFormat" id="docFormatSummary" value="Summary with timestamps">
|
||||||
|
<label id="label_summary" for="docFormatSummary">Summary with timestamps</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button class="submit-btn" id="submitButton" onclick="checkBoxes()" disabled>Submit</button>
|
||||||
|
|
||||||
|
<div class="progressbar" id="progressbar">
|
||||||
|
<div class="progress_fill"></div>
|
||||||
|
<span class="progress_text">0%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<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>
|
||||||
|
|||||||
@@ -15,22 +15,12 @@ try {
|
|||||||
getModuleNames: () => ipcRenderer.invoke('get-module-names')
|
getModuleNames: () => ipcRenderer.invoke('get-module-names')
|
||||||
})
|
})
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electron', {
|
|
||||||
progress: (callback) => ipcRenderer.on('progress', callback)
|
|
||||||
|
ipcRenderer.on("progress", (event, resp) => {
|
||||||
|
alert(`Finished step ${resp.curstep} of ${resp.totalsteps}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('audios', {
|
|
||||||
speakerAudios: (callback) => ipcRenderer.on('speakerAudios', callback)
|
|
||||||
})
|
|
||||||
contextBridge.exposeInMainWorld("submitSpeaker", {
|
|
||||||
submitSpeaker: (speaker_names) => {ipcRenderer.send("speaker_submit", speaker_names)}
|
|
||||||
})
|
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("download", {
|
|
||||||
file_download: () => {ipcRenderer.send("file_download")}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
ipcRenderer.on("error", (event, err) => {alert(err)})
|
ipcRenderer.on("error", (event, err) => {alert(err)})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error in preload.js");
|
console.log("Error in preload.js");
|
||||||
|
|||||||
+15
-171
@@ -33,6 +33,7 @@ uploadContainer.addEventListener("drop", (e) => {
|
|||||||
|
|
||||||
window.addEventListener('load', async (e) => {
|
window.addEventListener('load', async (e) => {
|
||||||
try {
|
try {
|
||||||
|
console.log("test");
|
||||||
loadLanguageOptions();
|
loadLanguageOptions();
|
||||||
const value = await window.onStartup.getModuleNames();
|
const value = await window.onStartup.getModuleNames();
|
||||||
loadAiOptions(value.ai_modules);
|
loadAiOptions(value.ai_modules);
|
||||||
@@ -54,16 +55,24 @@ language_option.addEventListener('change', (e)=>{
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//listener for the file explorer search when something got selected
|
|
||||||
videoUpload.addEventListener("change", () => {
|
videoUpload.addEventListener("change", () => {
|
||||||
try {
|
try {
|
||||||
if (videoUpload.files.length > 0) {
|
activateSubmitBtn(videoUpload.files.length > 0);
|
||||||
const file = videoUpload.files;
|
|
||||||
handleFiles(file);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//listener for the file explorer search when something got selected
|
||||||
|
videoUpload.addEventListener('change', () => {
|
||||||
|
try {
|
||||||
|
handleFiles(videoUpload.files);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error in manualBtn EventListener change");
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//listener for the file explorer search
|
//listener for the file explorer search
|
||||||
@@ -75,169 +84,4 @@ manualUploadBtn.addEventListener('click', () => {
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
stepButtons.forEach(btn => {
|
|
||||||
btn.addEventListener("click", () => {
|
|
||||||
try {
|
|
||||||
const step = parseInt(btn.dataset.step);
|
|
||||||
showStep(step);
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
prevBtn.addEventListener("click", () => {
|
|
||||||
try {
|
|
||||||
if (currentStep > 1) showStep(currentStep - 1);
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nextBtn.addEventListener("click", () => {
|
|
||||||
try {
|
|
||||||
if(currentStep < totalSteps) showStep(currentStep + 1);
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Checkboxlistener so that only one can be selected at a time
|
|
||||||
docFormat.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
if(docFormat.checked){
|
|
||||||
docFormatSummary1.checked = false;
|
|
||||||
docFormatSummary2.checked = false;
|
|
||||||
docFormatSummary3.checked = false;
|
|
||||||
docFormatCustom.checked = false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
docFormatSummary1.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
if(docFormatSummary1.checked){
|
|
||||||
docFormat.checked = false;
|
|
||||||
docFormatSummary2.checked = false;
|
|
||||||
docFormatSummary3.checked = false;
|
|
||||||
docFormatCustom.checked = false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
docFormatSummary2.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
if(docFormatSummary2.checked){
|
|
||||||
docFormatSummary1.checked = false;
|
|
||||||
docFormat.checked = false;
|
|
||||||
docFormatSummary3.checked = false;
|
|
||||||
docFormatCustom.checked = false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
docFormatSummary3.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
if(docFormatSummary3.checked){
|
|
||||||
docFormatSummary1.checked = false;
|
|
||||||
docFormatSummary2.checked = false;
|
|
||||||
docFormat.checked = false;
|
|
||||||
docFormatCustom.checked = false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
docFormatCustom.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
if(docFormatCustom.checked){
|
|
||||||
docFormatSummary1.checked = false;
|
|
||||||
docFormatSummary2.checked = false;
|
|
||||||
docFormatSummary3.checked = false;
|
|
||||||
docFormat.checked = false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Speaker change listener
|
|
||||||
cur_speaker.addEventListener("change", (e) =>{
|
|
||||||
try {
|
|
||||||
document.getElementById("speakerAudioViewer").src = valy[e.target.value].source;
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.audios.speakerAudios((event, arg) => {
|
|
||||||
setSpeakerAudiosValue(arg);
|
|
||||||
loadSpeakerOptions(arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
window.electron.progress((event, arg) => {
|
|
||||||
if(arg.curstep == 1){
|
|
||||||
setCircleOne();
|
|
||||||
}else if(arg.curstep == 2){
|
|
||||||
setCircleZwo();
|
|
||||||
} else if(arg.curstep == 3){
|
|
||||||
setCircleThree();
|
|
||||||
}else if(arg.curstep == 4){
|
|
||||||
setCircleFour();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function setCircleOne(){
|
|
||||||
try {
|
|
||||||
if(document.getElementById("box1").style.backgroundColor == "green"){
|
|
||||||
document.getElementById("box1").style.backgroundColor = "red";
|
|
||||||
}else{
|
|
||||||
document.getElementById("box1").style.backgroundColor = "green";
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
function setCircleZwo(){
|
|
||||||
try {
|
|
||||||
if(document.getElementById("box2").style.backgroundColor == "green"){
|
|
||||||
document.getElementById("box2").style.backgroundColor = "red";
|
|
||||||
}else{
|
|
||||||
document.getElementById("box2").style.backgroundColor = "green";
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
function setCircleThree(){
|
|
||||||
try {
|
|
||||||
if(document.getElementById("box3").style.backgroundColor == "green"){
|
|
||||||
document.getElementById("box3").style.backgroundColor = "red";
|
|
||||||
}else{
|
|
||||||
document.getElementById("box3").style.backgroundColor = "green";
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
function setCircleFour(){
|
|
||||||
try {
|
|
||||||
if(document.getElementById("box4").style.backgroundColor == "green"){
|
|
||||||
document.getElementById("box4").style.backgroundColor = "red";
|
|
||||||
}else{
|
|
||||||
document.getElementById("box4").style.backgroundColor = "green";
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+7
-128
@@ -1,4 +1,4 @@
|
|||||||
let currentVideoPath = null;
|
|
||||||
//function to check if one checkbox is at least klicked
|
//function to check if one checkbox is at least klicked
|
||||||
function checkBoxes() {
|
function checkBoxes() {
|
||||||
try {
|
try {
|
||||||
@@ -25,6 +25,7 @@ function checkBoxes() {
|
|||||||
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
||||||
var pathToLower = pathTest.toLowerCase();
|
var pathToLower = pathTest.toLowerCase();
|
||||||
if(testEndings.some(e => pathToLower.endsWith(e))){
|
if(testEndings.some(e => pathToLower.endsWith(e))){
|
||||||
|
document.getElementById("progressbar").style.visibility = "visible";
|
||||||
//assembly of the json for the main
|
//assembly of the json for the main
|
||||||
|
|
||||||
const selectedStyles = [checkedCounter];
|
const selectedStyles = [checkedCounter];
|
||||||
@@ -36,11 +37,6 @@ function checkBoxes() {
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.getElementById("testy").style.visibility = "visible"
|
|
||||||
document.getElementById("box1").style.backgroundColor = "red";
|
|
||||||
document.getElementById("box2").style.backgroundColor = "red";
|
|
||||||
document.getElementById("box3").style.backgroundColor = "red";
|
|
||||||
document.getElementById("box4").style.backgroundColor = "red";
|
|
||||||
console.log(selectedCheckboxes);
|
console.log(selectedCheckboxes);
|
||||||
const outputType = document.getElementById("output_type");
|
const outputType = document.getElementById("output_type");
|
||||||
const transcriptionType = document.getElementById("transkript_type");
|
const transcriptionType = document.getElementById("transkript_type");
|
||||||
@@ -48,15 +44,15 @@ function checkBoxes() {
|
|||||||
const sendingPackage = {
|
const sendingPackage = {
|
||||||
"video": {
|
"video": {
|
||||||
"module":"extraction-video-to-audio",
|
"module":"extraction-video-to-audio",
|
||||||
"inputVideoPath": pathTest
|
"inputVideoPath": pathTest,
|
||||||
|
"outputType": outputType.value
|
||||||
},
|
},
|
||||||
"transcription": {
|
"transcription": {
|
||||||
"module": transcriptionType.value
|
"module": transcriptionType.value
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"module":aiType.value,
|
"module":aiType.value,
|
||||||
"styles": selectedStyles,
|
"styles": selectedStyles
|
||||||
"outputType": outputType.value
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.submit.submit(sendingPackage)
|
window.submit.submit(sendingPackage)
|
||||||
@@ -109,7 +105,6 @@ function handleFiles(files) {
|
|||||||
const filePath = window.explorer.onFileDrop(files[0])
|
const filePath = window.explorer.onFileDrop(files[0])
|
||||||
videoUpload.files = files;
|
videoUpload.files = files;
|
||||||
fileName.textContent = `Chosen video: ${file.name}`;
|
fileName.textContent = `Chosen video: ${file.name}`;
|
||||||
currentVideoPath = filePath;
|
|
||||||
generateThumbnail(filePath);
|
generateThumbnail(filePath);
|
||||||
activateSubmitBtn(true);
|
activateSubmitBtn(true);
|
||||||
}
|
}
|
||||||
@@ -172,25 +167,6 @@ function loadTranscriptionOptions(options){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//function to load data type options to the drop down list
|
|
||||||
function loadDataTypeOptions(options){
|
|
||||||
try {
|
|
||||||
var menu = document.getElementById('output_type');
|
|
||||||
var object_holdy;
|
|
||||||
var choice ;
|
|
||||||
object_holdy = options
|
|
||||||
for(i = 0; i < options.length; i++){
|
|
||||||
choice = document.createElement('option');
|
|
||||||
choice.textContent = object_holdy[i].displayname;
|
|
||||||
choice.value = object_holdy[i].name;
|
|
||||||
menu.appendChild(choice);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Error in script.js function loadDataTypeOptions");
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//function to load language options to the drop down list
|
//function to load language options to the drop down list
|
||||||
function loadLanguageOptions(){
|
function loadLanguageOptions(){
|
||||||
try {
|
try {
|
||||||
@@ -204,48 +180,16 @@ function loadLanguageOptions(){
|
|||||||
choice.value = object_holdy[i];
|
choice.value = object_holdy[i];
|
||||||
menu.appendChild(choice);
|
menu.appendChild(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error in script.js loadLanguageOptions function");
|
console.log("Error in script.js loadLanguageOptions function");
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//function to load speaker options to the drop down list
|
|
||||||
function loadSpeakerOptions(options){
|
|
||||||
try {
|
|
||||||
var menu = document.getElementById('speaker_option');
|
|
||||||
var object_holdy;
|
|
||||||
var choice;
|
|
||||||
object_holdy = options.keys();
|
|
||||||
for(i = 0; i < options.length; i++){
|
|
||||||
choice = document.createElement('option');
|
|
||||||
choice.textContent = options[object_holdy[i]].name;
|
|
||||||
choice.value = options[object_holdy[i]].name;
|
|
||||||
menu.appendChild(choice);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Error in script.js loadSpeakerOptions function");
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//function to load speaker audio file options to the drop down list
|
|
||||||
function loadSpeakerAudio(option){
|
|
||||||
try {
|
|
||||||
var menu = document.getElementById('speakerAudioViewer');
|
|
||||||
var aud = document.createElement("source");
|
|
||||||
aud.src = options;
|
|
||||||
menu.appendChild(aud);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Error in script.js loadSpeakerAudio function");
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function activateSubmitBtn(hasFile){
|
function activateSubmitBtn(hasFile){
|
||||||
try {
|
try {
|
||||||
document.getElementById("submitButton").disabled = !hasFile;
|
submitButton.disabled = !hasFile;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@@ -270,68 +214,3 @@ function generateThumbnail(path){
|
|||||||
videoElement.style.maxHeight = 40;
|
videoElement.style.maxHeight = 40;
|
||||||
videoElement.autoplay = false;
|
videoElement.autoplay = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Step-navigation
|
|
||||||
const steps = document.querySelectorAll(".step");
|
|
||||||
const stepButtons = document.querySelectorAll(".step-item");
|
|
||||||
let currentStep = 1;
|
|
||||||
const totalSteps = steps.length;
|
|
||||||
|
|
||||||
function showStep(stepNumber) {
|
|
||||||
if (stepNumber < 1 || stepNumber > totalSteps){
|
|
||||||
console.error("StepNumber out of Bounds", stepNumber);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
steps.forEach(step => step.style.display = "none");
|
|
||||||
document.getElementById("step" + stepNumber).style.display = "block";
|
|
||||||
|
|
||||||
stepButtons.forEach(btn => btn.classList.remove("active"));
|
|
||||||
document.querySelector(`.step-item[data-step="${stepNumber}"]`).classList.add("active");
|
|
||||||
const activeBtn = document.querySelector(`.step-item[data-step="${stepNumber}"]`);
|
|
||||||
|
|
||||||
if(activeBtn) activeBtn.classList.add("active");
|
|
||||||
|
|
||||||
prevBtn.disabled = stepNumber == 1;
|
|
||||||
nextBtn.disabled = stepNumber === totalSteps;
|
|
||||||
currentStep = stepNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Audio value setter
|
|
||||||
var speakerAudios = {};
|
|
||||||
var speakerEndValues = {};
|
|
||||||
function setSpeakerAudiosValue(valy){
|
|
||||||
try {
|
|
||||||
speakerAudios = valy;
|
|
||||||
speakerRewriten = valy;
|
|
||||||
document.getElementById("speakerAudioViewer").src = valy.speakerA.source;
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rewriteSpeakerName(){
|
|
||||||
try {
|
|
||||||
var tempy = document.getElementById("cur_speaker").textContent;
|
|
||||||
speakerAudios[tempy].name = document.getElementById("newSpeaker").textContent;
|
|
||||||
document.getElementById("cur_speaker").textContent = document.getElementById("newSpeaker").textContent;
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendSpeakerPackages(){
|
|
||||||
try {
|
|
||||||
window.sendSpeakerPackages(speakerAudios);
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fileDownload() {
|
|
||||||
try {
|
|
||||||
window.download.file_download();
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Download failed:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+27
-318
@@ -6,33 +6,11 @@ body {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: #f2f3f4;
|
background-color: #f2f3f4;
|
||||||
gap: 10px;
|
gap: 15px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#h1 {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
margin: 0;
|
|
||||||
z-index: 20;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#h1-wrapper {
|
|
||||||
position: relative;
|
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
||||||
width: 770px;
|
|
||||||
height: 60px;
|
|
||||||
background-color: #FFF;
|
|
||||||
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
|
||||||
border-radius: 5px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-container {
|
.upload-container {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
@@ -113,73 +91,25 @@ input[type="file"] {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-group {
|
|
||||||
--borderColor: #007bfff5;
|
|
||||||
--borderWidth: .125em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-group input[type=checkbox] {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
vertical-align: middle;
|
|
||||||
background: #fff;
|
|
||||||
font-size: 1.8em;
|
|
||||||
border-radius: 0.125em;
|
|
||||||
display: inline-block;
|
|
||||||
border: var(--borderWidth) solid var(--borderColor);
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:before,
|
|
||||||
.checkbox-group input[type=checkbox]:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background: var(--borderColor);
|
|
||||||
width: calc(var(--borderWidth) * 3);
|
|
||||||
height: var(--borderWidth);
|
|
||||||
top: 50%;
|
|
||||||
left: 10%;
|
|
||||||
transform-origin: left center;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:before {
|
|
||||||
transform: rotate(45deg) translate(calc(var(--borderWidth) / -2), calc(var(--borderWidth) / -2)) scaleX(0);
|
|
||||||
transition: transform 200ms ease-in 200ms;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:after {
|
|
||||||
width: calc(var(--borderWidth) * 5);
|
|
||||||
transform: rotate(-45deg) translateY(calc(var(--borderWidth) * 2)) scaleX(0);
|
|
||||||
transform-origin: left center;
|
|
||||||
transition: transform 200ms ease-in;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:checked:before {
|
|
||||||
transform: rotate(45deg) translate(calc(var(--borderWidth) / -2), calc(var(--borderWidth) / -2)) scaleX(1);
|
|
||||||
transition: transform 200ms ease-in;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:checked:after {
|
|
||||||
width: calc(var(--borderWidth) * 5);
|
|
||||||
transform: rotate(-45deg) translateY(calc(var(--borderWidth) * 2)) scaleX(1);
|
|
||||||
transition: transform 200ms ease-out 200ms;
|
|
||||||
}
|
|
||||||
.checkbox-group input[type=checkbox]:focus {
|
|
||||||
outline: calc(var(--borderWidth) / 2) dotted rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-container{
|
.checkbox-container{
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-items: left;
|
align-items: center;
|
||||||
align-items: center;
|
gap: 5px;
|
||||||
gap: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox-group {
|
||||||
.submit-btn {
|
margin-top: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
margin-left: 80px;
|
margin-top: 10px;
|
||||||
margin-top: 30px;
|
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
background-color: #007BFF;
|
background-color: #007BFF;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -196,12 +126,13 @@ input[type="file"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mitte {
|
.mitte {
|
||||||
background-color: #FFF;
|
background-color: #FDFCFA;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 700px;
|
width: 700px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 40px;
|
padding: 5% 50px;
|
||||||
|
margin-top: 20px;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
border-color: black;
|
border-color: black;
|
||||||
@@ -210,11 +141,14 @@ input[type="file"] {
|
|||||||
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.progressbar{
|
.progressbar{
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 210px;
|
width: 210px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
margin: 50px 20px 5px 20px;
|
|
||||||
background: rgb(42, 46, 78);
|
background: rgb(42, 46, 78);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -239,10 +173,9 @@ input[type="file"] {
|
|||||||
|
|
||||||
.dropdownMenus {
|
.dropdownMenus {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: flex-end;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
margin-bottom: 30px;
|
gap: 150px;
|
||||||
gap: 170px;
|
|
||||||
padding: 2px 10px 2px 10px;
|
padding: 2px 10px 2px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,229 +184,5 @@ input[type="file"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.labelDiv {
|
.labelDiv {
|
||||||
gap: 60px;
|
gap: 200px;
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
overflow-wrap:inherit;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Step bar*/
|
|
||||||
.step-nav {
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
justify-content: center;
|
|
||||||
background: #fff;
|
|
||||||
padding: 10px 30px;
|
|
||||||
border-radius: 6px;
|
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-item {
|
|
||||||
padding: 10px 25px;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #eee;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
transition: 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-item.active {
|
|
||||||
background: #007BFF;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-item:hover {
|
|
||||||
background: #d9d9d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*panels*/
|
|
||||||
.step {
|
|
||||||
margin-top: 70px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Navigation arrows*/
|
|
||||||
.step-nav-arrows {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.middle-container-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 30px;
|
|
||||||
width: max-content;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navBtn {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 10px 25px;
|
|
||||||
background-color: #007BFF;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navBtn:disabled {
|
|
||||||
background-color: #ccc;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.testy{
|
|
||||||
background-color: #FFF;
|
|
||||||
display: flex;
|
|
||||||
width: auto;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
gap: 10px;
|
|
||||||
border: 0px;
|
|
||||||
border-color: black;
|
|
||||||
border-style: solid;
|
|
||||||
border-radius: 6px;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box2 {
|
|
||||||
background-color: red;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
padding: 5px;
|
|
||||||
border: 1px solid black;
|
|
||||||
margin: 5px;
|
|
||||||
border-radius: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-menu1 {
|
|
||||||
margin-left: 20px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger1 {
|
|
||||||
height: 45px;
|
|
||||||
margin: 0;
|
|
||||||
padding-top: 8px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: repeat(3, 1fr);
|
|
||||||
justify-items: center;
|
|
||||||
z-index: 120;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger1 div {
|
|
||||||
background-color: rgb(61, 61, 61);
|
|
||||||
position: relative;
|
|
||||||
width: 40px;
|
|
||||||
height: 5px;
|
|
||||||
margin-top: 0;
|
|
||||||
-webkit-transition: all 0.2s ease-in-out;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#toggle1 {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#toggle1:checked + .hamburger1 .top {
|
|
||||||
-webkit-transform: rotate(-45deg);
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
margin-top: 22.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#toggle1:checked + .hamburger1 .meat {
|
|
||||||
-webkit-transform: rotate(45deg);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
margin-top: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#toggle1:checked + .hamburger1 .bottom {
|
|
||||||
-webkit-transform: scale(0);
|
|
||||||
transform: scale(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#toggle1:checked ~ .menu1 {
|
|
||||||
height: 150px;
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Menu */
|
|
||||||
.menu1 {
|
|
||||||
position: absolute;
|
|
||||||
top: 55px;
|
|
||||||
left: 20px;
|
|
||||||
width: 240px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background-color: #1C3B69;
|
|
||||||
margin: 0;
|
|
||||||
display: -ms-grid;
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: 1fr repeat(4, 0.5fr);
|
|
||||||
grid-row-gap: 25px;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
clear: both;
|
|
||||||
width: auto;
|
|
||||||
text-align: center;
|
|
||||||
height: 0px;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: height 0.3s ease, width 0.3s ease;
|
|
||||||
z-index: 9999;
|
|
||||||
-webkit-transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu1 li:first-child {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu1 li:last-child {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.li1 {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 0;
|
|
||||||
font: 700 20px 'Oswald', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.li1:hover {
|
|
||||||
background-color: #FFF;
|
|
||||||
color: rgb(61, 61, 61);
|
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
-webkit-transition: all 0.3s ease;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#step2, #step3, #step5 {
|
|
||||||
font-size: larger;
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-btn {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 10px 20px;
|
|
||||||
margin-left: 80px;
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
background-color: #007BFF;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ let mainWindow;
|
|||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
mainWindow = new electron.BrowserWindow({
|
mainWindow = new electron.BrowserWindow({
|
||||||
width: 1200,
|
width: 800,
|
||||||
height: 800,
|
height: 800,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
@@ -124,12 +124,10 @@ electron.ipcMain.handle('get-module-names', async () => {
|
|||||||
// mainWindow.webContents.send("modules", module_array)
|
// mainWindow.webContents.send("modules", module_array)
|
||||||
// })
|
// })
|
||||||
|
|
||||||
var globalArgs = {}
|
|
||||||
var globalFinalHtmlPath = ""
|
|
||||||
|
|
||||||
electron.ipcMain.on("file_submit", async (event, args) => {
|
electron.ipcMain.on("file_submit", async (event, args) => {
|
||||||
try {
|
try {
|
||||||
globalArgs = args
|
|
||||||
let curstep = 0
|
let curstep = 0
|
||||||
let totalsteps = 3 + args.document.styles.length
|
let totalsteps = 3 + args.document.styles.length
|
||||||
|
|
||||||
@@ -143,7 +141,7 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
|
|
||||||
console.log("\n\n Running the Video to Audio Extractor");
|
console.log("\n\n Running the Video to Audio Extractor");
|
||||||
// This code handles the Video to Audio extraction module call
|
// This code handles the Video to Audio extraction module call
|
||||||
await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: mapFunctions.get(args.transcription.module).audioformat}).then(resp => {
|
await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => {
|
||||||
console.log(resp);
|
console.log(resp);
|
||||||
audiopath = resp
|
audiopath = resp
|
||||||
curstep++
|
curstep++
|
||||||
@@ -185,11 +183,9 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
// TODO implement documentation module
|
// TODO implement documentation module
|
||||||
// This code handles the Text to Document processing module call
|
// This code handles the Text to Document processing module call
|
||||||
for (let i = 0; i < args.document.styles.length; i++) {
|
for (let i = 0; i < args.document.styles.length; i++) {
|
||||||
console.log(`\n\n Running the LLM for Document Style ${i+1}`);
|
await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => {
|
||||||
|
|
||||||
await mapFunctions.get("module-handler").function(args.document.module, {inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/standard_meeting_report.txt", language: "en"}).then(resp => {
|
|
||||||
console.log(resp);
|
console.log(resp);
|
||||||
globalFinalHtmlPath = resp
|
transcriptpath = resp
|
||||||
curstep++
|
curstep++
|
||||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@@ -197,24 +193,6 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
return
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO actually implement this functionality
|
|
||||||
// Module to get the first few lines for each speaker to send to the frontend
|
|
||||||
// await mapFunctions.get("speaker-getter-idfk").function(transcriptpath).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
// transcriptpath = resp
|
|
||||||
// curstep++
|
|
||||||
// mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
|
||||||
|
|
||||||
// // {
|
|
||||||
// // speakerA: {source: "Pfad zur Audio File"},
|
|
||||||
// // speakerB:.....
|
|
||||||
// // }
|
|
||||||
mainWindow.webContents.send("speakers", {speakerA:"pfad1", speakerB:"pfad2"})
|
|
||||||
// }).catch(err => {
|
|
||||||
// mainWindow.webContents.send("error", err)
|
|
||||||
// return
|
|
||||||
// })
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -222,9 +200,6 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.ipcMain.on("file_download", async() => {
|
|
||||||
await mapFunctions.get("htmlDocumentConverter").convert({inputPath:globalFinalHtmlPath, format: globalArgs.document.outputType, showDialog: true});
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
let q =
|
let q =
|
||||||
|
|||||||
Generated
+39
-1884
File diff suppressed because it is too large
Load Diff
+3
-5
@@ -3,14 +3,12 @@
|
|||||||
"@google/genai": "^1.30.0",
|
"@google/genai": "^1.30.0",
|
||||||
"@types/axios": "^0.9.36",
|
"@types/axios": "^0.9.36",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"cli-progress": "^3.12.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"electron": "^39.1.1",
|
"electron": "^39.1.1",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"ffmpeg-static": "^5.2.0",
|
"ffmpeg-static": "^5.2.0",
|
||||||
"fluent-ffmpeg": "^2.1.3",
|
"fluent-ffmpeg": "^2.1.3"
|
||||||
"html-to-docx": "^1.8.0",
|
|
||||||
"mocha": "^11.7.5",
|
|
||||||
"puppeteer": "^24.33.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cli-progress": "^3.11.6",
|
"@types/cli-progress": "^3.11.6",
|
||||||
@@ -29,7 +27,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron main.js",
|
"start": "electron main.js",
|
||||||
"test": "mocha ./test/unit/test.js"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fastapi
|
||||||
|
uvicorn
|
||||||
|
pytest
|
||||||
+2
-4
@@ -6,19 +6,17 @@ platform = process.platform
|
|||||||
mainDir = __dirname
|
mainDir = __dirname
|
||||||
fs = require("fs")
|
fs = require("fs")
|
||||||
readline = require("readline")
|
readline = require("readline")
|
||||||
|
|
||||||
puppeteer = require("puppeteer")
|
|
||||||
htmltodocx = require("html-to-docx")
|
|
||||||
config = require("./config/config")
|
config = require("./config/config")
|
||||||
|
|
||||||
ffmpegPath = require('ffmpeg-static');
|
ffmpegPath = require('ffmpeg-static');
|
||||||
ffmpeg = require('fluent-ffmpeg');
|
ffmpeg = require('fluent-ffmpeg');
|
||||||
path = require('path');
|
path = require('path');
|
||||||
// cliProgress = require('cli-progress');
|
cliProgress = require('cli-progress');
|
||||||
|
|
||||||
// { app, BrowserWindow, ipcMain, dialog } = require('electron');
|
// { app, BrowserWindow, ipcMain, dialog } = require('electron');
|
||||||
|
|
||||||
electron = require('electron');
|
electron = require('electron');
|
||||||
|
genai = require("@google/genai");
|
||||||
|
|
||||||
axios = require("axios")
|
axios = require("axios")
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
//node show-models.js, remember to set SAIA_API_KEY in your environment before running the script
|
|
||||||
|
|
||||||
const SAIA_API_KEY = process.env.SAIA_API_KEY;
|
|
||||||
const SAIA_MODELS_URL = "https://chat-ai.academiccloud.de/v1/models";
|
|
||||||
|
|
||||||
// Script to list available models
|
|
||||||
(async () => {
|
|
||||||
if (!SAIA_API_KEY) {
|
|
||||||
console.error("ERROR: SAIA_API_KEY environment variable is not set!");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Fetching available models from SAIA...\n");
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(SAIA_MODELS_URL, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
|
||||||
"Accept": "application/json"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`SAIA API error (${response.status}): ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
console.log("Available models:");
|
|
||||||
console.log(JSON.stringify(data, null, 2));
|
|
||||||
|
|
||||||
if (data.data && Array.isArray(data.data)) {
|
|
||||||
console.log("\n\nModel IDs:");
|
|
||||||
data.data.forEach(model => {
|
|
||||||
console.log(`- ${model.id}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching models:", error);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const puppeteer = require('puppeteer');
|
|
||||||
const htmlToDocx = require('html-to-docx');
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
const os = require('os');
|
|
||||||
|
|
||||||
const outputDir = path.join(__dirname, "../../../storage/documents");
|
|
||||||
|
|
||||||
if (!fs.existsSync(outputDir)) {
|
|
||||||
fs.mkdirSync(outputDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function showSaveDialog(defaultName, format) {
|
|
||||||
const platform = os.platform();
|
|
||||||
|
|
||||||
if (platform === 'darwin') {
|
|
||||||
// macOS
|
|
||||||
const applescript = `
|
|
||||||
set defaultName to "${defaultName}.${format}"
|
|
||||||
set theFile to choose file name with prompt "Dokument speichern als:" default name defaultName
|
|
||||||
POSIX path of theFile
|
|
||||||
`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = execSync(`osascript -e '${applescript}'`, { encoding: 'utf8' });
|
|
||||||
return result.trim();
|
|
||||||
} catch (err) {
|
|
||||||
if (err.status === 1) return null; // User canceled
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
} else if (platform === 'win32') {
|
|
||||||
// Windows
|
|
||||||
const powershell = `
|
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
|
||||||
$dialog = New-Object System.Windows.Forms.SaveFileDialog
|
|
||||||
$dialog.FileName = "${defaultName}.${format}"
|
|
||||||
$dialog.Filter = "${format.toUpperCase()} Dateien (*.${format})|*.${format}|Alle Dateien (*.*)|*.*"
|
|
||||||
$dialog.Title = "Dokument speichern als"
|
|
||||||
$result = $dialog.ShowDialog()
|
|
||||||
if ($result -eq 'OK') { $dialog.FileName }
|
|
||||||
`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = execSync(`powershell -Command "${powershell.replace(/\n/g, '; ')}"`, {
|
|
||||||
encoding: 'utf8'
|
|
||||||
});
|
|
||||||
return result.trim() || null;
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Linux - zenity oder kdialog
|
|
||||||
try {
|
|
||||||
const result = execSync(
|
|
||||||
`zenity --file-selection --save --confirm-overwrite --filename="${defaultName}.${format}"`,
|
|
||||||
{ encoding: 'utf8' }
|
|
||||||
);
|
|
||||||
return result.trim();
|
|
||||||
} catch (err) {
|
|
||||||
try {
|
|
||||||
const result = execSync(
|
|
||||||
`kdialog --getsavefilename . "${defaultName}.${format}"`,
|
|
||||||
{ encoding: 'utf8' }
|
|
||||||
);
|
|
||||||
return result.trim();
|
|
||||||
} catch (err2) {
|
|
||||||
// Fallback
|
|
||||||
return path.join(os.homedir(), 'Downloads', `${defaultName}.${format}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const module_exports = {
|
|
||||||
name: "htmlDocumentConverter",
|
|
||||||
type: "converter",
|
|
||||||
displayname: "HTML Document Converter",
|
|
||||||
description: "Converts LLM-generated HTML to PDF, DOCX, TXT, or HTML",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main conversion function
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {string} options.inputPath - Path to the HTML input
|
|
||||||
* @param {string} options.format - 'pdf' | 'docx' | 'html' | 'txt'
|
|
||||||
* @param {string} [options.outputName] - Optional output filename (without extension)
|
|
||||||
* @param {boolean} [options.showDialog] - Show save dialog (default: false in module mode, true in CLI mode)
|
|
||||||
*/
|
|
||||||
async convert({ inputPath, format = 'pdf', outputName, showDialog = false }) {
|
|
||||||
if (!fs.existsSync(inputPath)) {
|
|
||||||
throw new Error(`Input file not found: ${inputPath}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ext = path.extname(inputPath).toLowerCase();
|
|
||||||
const baseName = outputName || path.basename(inputPath, ext);
|
|
||||||
|
|
||||||
let outputFile;
|
|
||||||
|
|
||||||
if (showDialog) {
|
|
||||||
// Zeige nativen Dialog
|
|
||||||
outputFile = await showSaveDialog(baseName, format);
|
|
||||||
if (!outputFile) {
|
|
||||||
console.log('Speichervorgang abgebrochen.');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Nutze Standard-Ausgabeverzeichnis
|
|
||||||
outputFile = path.join(outputDir, `${baseName}.${format.toLowerCase()}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let htmlContent = fs.readFileSync(inputPath, 'utf8');
|
|
||||||
|
|
||||||
// Remove <think> tags if present
|
|
||||||
htmlContent = htmlContent.replace(/<think>[\s\S]*?<\/think>/gi, '');
|
|
||||||
|
|
||||||
switch (format.toLowerCase()) {
|
|
||||||
case 'html':
|
|
||||||
fs.writeFileSync(outputFile, htmlContent, 'utf8');
|
|
||||||
break;
|
|
||||||
case 'pdf':
|
|
||||||
await this.htmlToPDF(htmlContent, outputFile);
|
|
||||||
break;
|
|
||||||
case 'docx':
|
|
||||||
await this.htmlToDOCX(htmlContent, outputFile);
|
|
||||||
break;
|
|
||||||
case 'txt':
|
|
||||||
fs.writeFileSync(outputFile, this.htmlToTXT(htmlContent), 'utf8');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Unsupported format: ${format}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Erfolgreich gespeichert: ${outputFile}`);
|
|
||||||
return outputFile;
|
|
||||||
},
|
|
||||||
|
|
||||||
// HTML → PDF
|
|
||||||
async htmlToPDF(html, outputPath) {
|
|
||||||
const browser = await puppeteer.launch({
|
|
||||||
headless: true,
|
|
||||||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
||||||
});
|
|
||||||
const page = await browser.newPage();
|
|
||||||
await page.setContent(html, { waitUntil: 'networkidle0' });
|
|
||||||
await page.pdf({
|
|
||||||
path: outputPath,
|
|
||||||
format: 'A4',
|
|
||||||
printBackground: true,
|
|
||||||
margin: { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' }
|
|
||||||
});
|
|
||||||
await browser.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
// HTML → DOCX
|
|
||||||
async htmlToDOCX(html, outputPath) {
|
|
||||||
const buffer = await htmlToDocx(html);
|
|
||||||
fs.writeFileSync(outputPath, buffer);
|
|
||||||
},
|
|
||||||
|
|
||||||
// HTML → TXT (rudimentär)
|
|
||||||
htmlToTXT(html) {
|
|
||||||
return html.replace(/<[^>]*>/g, '').replace(/\s+\n/g, '\n').trim();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = module_exports;
|
|
||||||
|
|
||||||
// CLI usage mit Dialog
|
|
||||||
if (require.main === module) {
|
|
||||||
(async () => {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
if (args.length < 1) {
|
|
||||||
console.log('Usage: node htmlDocumentConverter.js <input.html> [format]');
|
|
||||||
console.log('Formats: pdf (default), docx, html, txt');
|
|
||||||
console.log('');
|
|
||||||
console.log('Ein nativer "Speichern unter" Dialog wird automatisch geöffnet.');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputPath = args[0];
|
|
||||||
const format = args[1] || 'pdf';
|
|
||||||
|
|
||||||
try {
|
|
||||||
await module_exports.convert({
|
|
||||||
inputPath,
|
|
||||||
format,
|
|
||||||
showDialog: true
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Konvertierung fehlgeschlagen:', err.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
@@ -24,11 +24,17 @@ module.exports = {
|
|||||||
outputType: String // Audio file output format
|
outputType: String // Audio file output format
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
let progressBar = new cliProgress.SingleBar({
|
||||||
|
format: 'Processing |{bar}| {percentage}% | {timemark}',
|
||||||
|
barCompleteChar: '\u2588',
|
||||||
|
barIncompleteChar: '\u2591',
|
||||||
|
hideCursor: true
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.extractAudioFromVideo(parameter.inputVideoPath, parameter.outputType)
|
this.extractAudioFromVideo(parameter.inputVideoPath, progressBar, parameter.outputType)
|
||||||
.then((resp) => resolve(resp))
|
.then((resp) => resolve(resp))
|
||||||
.catch((err) => {reject(err)});
|
.catch((err) => console.error(err));
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(parameter.outputType);
|
console.log(parameter.outputType);
|
||||||
@@ -46,7 +52,7 @@ module.exports = {
|
|||||||
* - Shows CLI progress bar
|
* - Shows CLI progress bar
|
||||||
* - Handles errors gracefully (without errors)
|
* - Handles errors gracefully (without errors)
|
||||||
*/
|
*/
|
||||||
extractAudioFromVideo: async function (videoFilePath, outputType){
|
extractAudioFromVideo: async function (videoFilePath, progressBar, outputType){
|
||||||
let inputVideoName = path.basename(videoFilePath, path.extname(videoFilePath));
|
let inputVideoName = path.basename(videoFilePath, path.extname(videoFilePath));
|
||||||
let outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`);
|
let outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`);
|
||||||
|
|
||||||
@@ -57,17 +63,28 @@ module.exports = {
|
|||||||
// .audioCodec('pcm_s16le')
|
// .audioCodec('pcm_s16le')
|
||||||
.audioChannels(1)
|
.audioChannels(1)
|
||||||
.audioFrequency(16000)
|
.audioFrequency(16000)
|
||||||
|
// .setFfmpegPath("./ffmpeg.exe")
|
||||||
|
.on('progress', (progress) => {
|
||||||
|
if (!progressBar.isActive) progressBar.start(100, 0, { timemark: '00:00:00' });
|
||||||
|
if (progress.percent) {
|
||||||
|
progressBar.update(progress.percent, { timemark: progress.timemark });
|
||||||
|
}
|
||||||
|
})
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
|
progressBar.update(100, { timemark: 'done' });
|
||||||
|
progressBar.stop();
|
||||||
|
console.log(`Extraction completed: ${outputAudioPath}`);
|
||||||
resolve(outputAudioPath);
|
resolve(outputAudioPath);
|
||||||
})
|
})
|
||||||
.on('error', (err) => {
|
.on('error', (err) => {
|
||||||
// console.error(`failed_audio_extraction on type ${outputType}: ${err.message}`);
|
progressBar.stop();
|
||||||
|
console.error(`failed_audio_extraction on type ${outputType}: ${err.message}`);
|
||||||
reject(err);
|
reject(err);
|
||||||
})
|
})
|
||||||
.save(outputAudioPath);
|
.save(outputAudioPath);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.log(error);
|
console.log();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,36 +21,30 @@ module.exports = {
|
|||||||
const raw = fs.readFileSync(args.jsonPath, "utf-8");
|
const raw = fs.readFileSync(args.jsonPath, "utf-8");
|
||||||
inputJson = JSON.parse(raw);
|
inputJson = JSON.parse(raw);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.error("Failed to load JSON from file:", e);
|
console.error("Failed to load JSON from file:", e);
|
||||||
reject(e)
|
return { error: "Could not read JSON from file path." };
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// JSON parsen
|
// JSON parsen
|
||||||
if (typeof args === "string") {
|
if (typeof args === "string") {
|
||||||
try {
|
try {
|
||||||
await new Promise((res, rej) => {
|
await new Promise((res) => {
|
||||||
fs.readFile(args, 'utf8', function (err, data) {
|
fs.readFile(args, 'utf8', function (err, data) {
|
||||||
if (err){
|
if (err) throw err;
|
||||||
rej(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
inputJson = JSON.parse(data);
|
inputJson = JSON.parse(data);
|
||||||
res()
|
res()
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.log("Invalid JSON in summarize-transcription");
|
console.log("Invalid JSON in summarize-transcription");
|
||||||
// console.log(e)
|
console.log(e)
|
||||||
reject(e)
|
return { error: "Invalid JSON" };
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const words = inputJson.words;
|
const words = inputJson.words;
|
||||||
if (!Array.isArray(words)) {
|
if (!Array.isArray(words)) {
|
||||||
reject("No words Array found")
|
return { error: "No words Array found" };
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
|
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
|
||||||
@@ -142,11 +136,11 @@ module.exports = {
|
|||||||
const txtPath = path.join(outputDir, "transcription_result.txt");
|
const txtPath = path.join(outputDir, "transcription_result.txt");
|
||||||
fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
|
fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
|
||||||
|
|
||||||
// console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
|
console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
|
||||||
|
|
||||||
resolve(jsonPath);
|
resolve(jsonPath);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// console.error("Error saving Summary:", err);
|
console.error("Error saving Summary:", err);
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,35 +32,29 @@ module.exports = {
|
|||||||
inputJson = JSON.parse(raw);
|
inputJson = JSON.parse(raw);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to load JSON from file:", e);
|
console.error("Failed to load JSON from file:", e);
|
||||||
reject("Could not read JSON from file path.")
|
return { error: "Could not read JSON from file path." };
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// JSON parsen
|
// JSON parsen
|
||||||
if (typeof args === "string") {
|
if (typeof args === "string") {
|
||||||
try {
|
try {
|
||||||
await new Promise((res, rej) => {
|
await new Promise((res) => {
|
||||||
fs.readFile(args, 'utf8', function (err, data) {
|
fs.readFile(args, 'utf8', function (err, data) {
|
||||||
if (err){
|
if (err) throw err;
|
||||||
rej(err)
|
inputJson = JSON.parse(data);
|
||||||
return
|
res()
|
||||||
}
|
});
|
||||||
inputJson = JSON.parse(data);
|
})
|
||||||
res()
|
} catch (e) {
|
||||||
});
|
console.log("Invalid JSON in summarize-transcription");
|
||||||
})
|
console.log(e)
|
||||||
} catch (e) {
|
return { error: "Invalid JSON" };
|
||||||
// console.log("Invalid JSON in summarize-transcription");
|
}
|
||||||
// console.log(e)
|
|
||||||
reject(e)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const words = inputJson.words;
|
const words = inputJson.words;
|
||||||
if (!Array.isArray(words)) {
|
if (!Array.isArray(words)) {
|
||||||
reject("No words Array found")
|
return { error: "No words Array found" };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
|
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
|
||||||
@@ -76,7 +70,7 @@ module.exports = {
|
|||||||
if (!currentSpeaker) currentSpeaker = w.speaker;
|
if (!currentSpeaker) currentSpeaker = w.speaker;
|
||||||
if (startTime === null) startTime = w.start;
|
if (startTime === null) startTime = w.start;
|
||||||
endTime = w.end;
|
endTime = w.end;
|
||||||
|
|
||||||
//speaker changing
|
//speaker changing
|
||||||
if (currentSpeaker !== w.speaker && currentSentence) {
|
if (currentSpeaker !== w.speaker && currentSentence) {
|
||||||
result.push({
|
result.push({
|
||||||
@@ -138,10 +132,10 @@ module.exports = {
|
|||||||
const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`);
|
const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`);
|
||||||
fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
|
fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
|
||||||
|
|
||||||
// console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
|
console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
|
||||||
resolve(jsonPath);
|
resolve(jsonPath);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// console.error("Error saving Summary:", err);
|
console.error("Error saving Summary:", err);
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,136 +1,8 @@
|
|||||||
const fs = require('fs');
|
module.exports = {
|
||||||
const path = require('path');
|
name:"chatgpt", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()"
|
||||||
|
type:"llm", // value used to differentiate each module to order them in the UI
|
||||||
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
|
displayname:"ChatGPT", // The displayname used within the UI
|
||||||
|
async function(parameter){
|
||||||
if (!fs.existsSync(outputDir)) {
|
// TODO add code to actually send the transcript to ChatGPT and get a response back
|
||||||
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here"
|
|
||||||
const SAIA_API_KEY = process.env.SAIA_API_KEY; // Ensure SAIA API key is set in environment variables
|
|
||||||
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action
|
|
||||||
|
|
||||||
const module_exports = {
|
|
||||||
name: "llm-saia_openai_gpt",
|
|
||||||
type: "llm",
|
|
||||||
displayname: "GPT 120B",
|
|
||||||
description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform",
|
|
||||||
|
|
||||||
async function(parameter) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
|
||||||
// console.log("SAIA OpenAI GPT module invoked with parameters:", parameter);
|
|
||||||
|
|
||||||
resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
|
|
||||||
parameter.inputTranscriptPath, // Path to input transcript file
|
|
||||||
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
|
|
||||||
parameter.language // Language for the document which is chosen in the front end by the user
|
|
||||||
));
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error in SAIA OpenAI GPT module:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
|
||||||
return new Promise(async(resolve, reject) => {
|
|
||||||
try {
|
|
||||||
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
|
||||||
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
|
|
||||||
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
|
|
||||||
|
|
||||||
// --- REST CALL ---
|
|
||||||
const response = await fetch(SAIA_URL, { //safe model response in variable
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
|
||||||
"Accept": "application/json",
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
model: "openai-gpt-oss-120b",
|
|
||||||
messages: [
|
|
||||||
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
|
|
||||||
{ role: "user", content: promptText }
|
|
||||||
],
|
|
||||||
temperature: 0
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) { //ok is true when a responce was successfull
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`SAIA API error (${response.status}): ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
// Get generated text from response or default to empty string (if null)
|
|
||||||
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
|
|
||||||
const output = data.choices?.[0]?.message?.content || "";
|
|
||||||
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
|
|
||||||
// console.log(inputTranscriptName);
|
|
||||||
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
|
|
||||||
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
|
|
||||||
|
|
||||||
// console.log("Generated document written to:", outPath);
|
|
||||||
resolve(outPath)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error generating SAIA content:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = module_exports;
|
|
||||||
|
|
||||||
// CLI Mode: Allow direct execution
|
|
||||||
if (require.main === module) {
|
|
||||||
(async () => {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
if (args.length < 2) {
|
|
||||||
console.error("Usage: node llm-openai-gpt.js <transcriptPath> <documentTypePath> [language]");
|
|
||||||
console.error("Example: node llm-openai-gpt.js ./transcript.json ./docType.txt de");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [transcriptPath, documentTypePath, language] = args;
|
|
||||||
|
|
||||||
// Check if API key is set
|
|
||||||
if (!SAIA_API_KEY) {
|
|
||||||
console.error("ERROR: SAIA_API_KEY environment variable is not set!");
|
|
||||||
console.error("Please set it with: export SAIA_API_KEY='your_api_key_here'");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if files exist
|
|
||||||
if (!fs.existsSync(transcriptPath)) {
|
|
||||||
console.error(`ERROR: Transcript file not found: ${transcriptPath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(documentTypePath)) {
|
|
||||||
console.error(`ERROR: Document type file not found: ${documentTypePath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Starting document generation...");
|
|
||||||
console.log(`Transcript: ${transcriptPath}`);
|
|
||||||
console.log(`Document Type: ${documentTypePath}`);
|
|
||||||
console.log(`Language: ${language || 'en (default)'}`);
|
|
||||||
|
|
||||||
await module_exports.createDocumentFromTranscript(
|
|
||||||
transcriptPath,
|
|
||||||
documentTypePath,
|
|
||||||
language || 'en'
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Done!");
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
@@ -1,134 +1,76 @@
|
|||||||
const fs = require('fs');
|
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
|
|
||||||
|
|
||||||
if (!fs.existsSync(outputDir)) {
|
if (!fs.existsSync(outputDir)) {
|
||||||
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
|
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here"
|
// Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here"
|
||||||
const GEMINI_API_KEY = process.env.GOOGLE_API_KEY; // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here"
|
|
||||||
const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"; // URL for the REST call, used model and action
|
|
||||||
|
|
||||||
const module_exports = {
|
const GEMINI_API_KEY = process.env.GOOGLE_API_KEY; // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here"
|
||||||
|
const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"; //URL for the REST call, used model and action
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
name: "llm-gemini",
|
name: "llm-gemini",
|
||||||
type: "llm",
|
type: "llm",
|
||||||
displayname: "Gemini LLM",
|
displayname: "Gemini LLM",
|
||||||
description: "Generates documents using Google Gemini LLM",
|
description: "Generates documents using Google Gemini LLM",
|
||||||
|
|
||||||
async function(parameter) {
|
async function(parameter) {
|
||||||
return new Promise(async (resolve, reject) => {
|
try {
|
||||||
try {
|
console.log("Gemini LLM module invoked with parameters:", parameter);
|
||||||
// console.log("Gemini LLM module invoked with parameters:", parameter);
|
|
||||||
|
|
||||||
resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
|
await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
|
||||||
parameter.inputTranscriptPath, // Path to input transcript file
|
parameter.inputTranscriptPath, // Path to input transcript file
|
||||||
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
|
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
|
||||||
parameter.language // Language for the document which is chosen in the front end by the user
|
parameter.language // Language for the document which is chosen in the front end by the user
|
||||||
));
|
);
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error in Gemini LLM module:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in Gemini LLM module:", error);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
||||||
return new Promise(async(resolve, reject) => {
|
try {
|
||||||
try {
|
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
||||||
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
|
||||||
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
|
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
|
||||||
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
|
|
||||||
|
|
||||||
// --- REST CALL ---
|
// --- REST CALL ---
|
||||||
const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable
|
const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
contents: [
|
contents: [
|
||||||
{
|
{
|
||||||
parts: [
|
parts: [
|
||||||
{ text: promptText } // Input prompt for content generation
|
{ text: promptText } // Input prompt for content generation
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) { //ok is true when a responce was successfull
|
if (!response.ok) { //ok is true when a responce was successfull
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
throw new Error(`Gemini API error (${response.status}): ${text}`);
|
throw new Error(`Gemini API error (${response.status}): ${text}`);
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
// Get generated text from response or default to empty string (if null)
|
|
||||||
const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || "";
|
|
||||||
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
|
|
||||||
// console.log(inputTranscriptName);
|
|
||||||
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
|
|
||||||
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
|
|
||||||
|
|
||||||
// console.log("Generated document written to:", outPath);
|
|
||||||
resolve(outPath)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error generating Gemini content:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Get generated text from response or default to empty string (if null)
|
||||||
|
const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || "";
|
||||||
|
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
|
||||||
|
console.log(inputTranscriptName);
|
||||||
|
const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name
|
||||||
|
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
|
||||||
|
|
||||||
|
console.log("Generated document written to:", outPath);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error generating Gemini content:", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = module_exports;
|
|
||||||
|
|
||||||
// CLI Mode: Allow direct execution
|
|
||||||
if (require.main === module) {
|
|
||||||
(async () => {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
if (args.length < 2) {
|
|
||||||
console.error("Usage: node llm-gemini.js <transcriptPath> <documentTypePath> [language]");
|
|
||||||
console.error("Example: node llm-gemini.js ./transcript.json ./docType.txt de");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [transcriptPath, documentTypePath, language] = args;
|
|
||||||
|
|
||||||
// Check if API key is set
|
|
||||||
if (!GEMINI_API_KEY) {
|
|
||||||
console.error("ERROR: GOOGLE_API_KEY environment variable is not set!");
|
|
||||||
console.error("Please set it with: export GOOGLE_API_KEY='your_api_key_here'");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if files exist
|
|
||||||
if (!fs.existsSync(transcriptPath)) {
|
|
||||||
console.error(`ERROR: Transcript file not found: ${transcriptPath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(documentTypePath)) {
|
|
||||||
console.error(`ERROR: Document type file not found: ${documentTypePath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Starting document generation...");
|
|
||||||
console.log(`Transcript: ${transcriptPath}`);
|
|
||||||
console.log(`Document Type: ${documentTypePath}`);
|
|
||||||
console.log(`Language: ${language || 'en (default)'}`);
|
|
||||||
|
|
||||||
await module_exports.createDocumentFromTranscript(
|
|
||||||
transcriptPath,
|
|
||||||
documentTypePath,
|
|
||||||
language || 'en'
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Done!");
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
|
|
||||||
|
|
||||||
if (!fs.existsSync(outputDir)) {
|
|
||||||
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here"
|
|
||||||
const SAIA_API_KEY = process.env.SAIA_API_KEY;
|
|
||||||
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action
|
|
||||||
|
|
||||||
const module_exports = {
|
|
||||||
name: "qwen3-235b-a22b",
|
|
||||||
type: "llm",
|
|
||||||
displayname: "QWEN 3 235B",
|
|
||||||
description: "Generates documents using QWEN 3 235B via SAIA platform",
|
|
||||||
|
|
||||||
async function(parameter) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
|
||||||
// console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
|
|
||||||
|
|
||||||
resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
|
|
||||||
parameter.inputTranscriptPath, // Path to input transcript file
|
|
||||||
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
|
|
||||||
parameter.language // Language for the document which is chosen in the front end by the user
|
|
||||||
));
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error in SAIA QWEN 3 235B module:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
|
||||||
return new Promise(async(resolve, reject) => {
|
|
||||||
try {
|
|
||||||
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
|
||||||
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
|
|
||||||
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
|
|
||||||
|
|
||||||
// --- REST CALL ---
|
|
||||||
const response = await fetch(SAIA_URL, { //safe model response in variable
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
|
||||||
"Accept": "application/json",
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
model: "qwen3-235b-a22b",
|
|
||||||
messages: [
|
|
||||||
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
|
|
||||||
{ role: "user", content: promptText }
|
|
||||||
],
|
|
||||||
temperature: 0
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) { //ok is true when a responce was successfull
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`SAIA API error (${response.status}): ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
// Get generated text from response or default to empty string (if null)
|
|
||||||
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
|
|
||||||
const output = data.choices?.[0]?.message?.content || "";
|
|
||||||
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
|
|
||||||
// console.log(inputTranscriptName);
|
|
||||||
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
|
|
||||||
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
|
|
||||||
|
|
||||||
// console.log("Generated document written to:", outPath);
|
|
||||||
resolve(outPath)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
// console.error("Error generating SAIA content:", error);
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = module_exports;
|
|
||||||
|
|
||||||
// CLI Mode: Allow direct execution
|
|
||||||
if (require.main === module) {
|
|
||||||
(async () => {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
if (args.length < 2) {
|
|
||||||
console.error("Usage: node qwen3.js <transcriptPath> <documentTypePath> [language]");
|
|
||||||
console.error("Example: node qwen3.js ./transcript.json ./docType.txt de");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [transcriptPath, documentTypePath, language] = args;
|
|
||||||
|
|
||||||
// Check if API key is set
|
|
||||||
if (!SAIA_API_KEY) {
|
|
||||||
console.error("ERROR: SAIA_API_KEY environment variable is not set!");
|
|
||||||
console.error("Please set it with: export SAIA_API_KEY='your_api_key_here'");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if files exist
|
|
||||||
if (!fs.existsSync(transcriptPath)) {
|
|
||||||
console.error(`ERROR: Transcript file not found: ${transcriptPath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(documentTypePath)) {
|
|
||||||
console.error(`ERROR: Document type file not found: ${documentTypePath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Starting document generation...");
|
|
||||||
console.log(`Transcript: ${transcriptPath}`);
|
|
||||||
console.log(`Document Type: ${documentTypePath}`);
|
|
||||||
console.log(`Language: ${language || 'en (default)'}`);
|
|
||||||
|
|
||||||
await module_exports.createDocumentFromTranscript(
|
|
||||||
transcriptPath,
|
|
||||||
documentTypePath,
|
|
||||||
language || 'en'
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Done!");
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
Submodule services/modules/transcription-local/whisper.cpp deleted from 999a7e0cbf
@@ -78,7 +78,7 @@ function saveTranscript(transcript, sessionId) {
|
|||||||
const outputPath = path.join(outputDir, `${sessionId}.json`);
|
const outputPath = path.join(outputDir, `${sessionId}.json`);
|
||||||
fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2));
|
fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2));
|
||||||
|
|
||||||
// console.log(`Transcript saved: ${outputPath}`);
|
console.log(`Transcript saved: ${outputPath}`);
|
||||||
|
|
||||||
return outputPath;
|
return outputPath;
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,6 @@ module.exports = {
|
|||||||
name: 'assembly',
|
name: 'assembly',
|
||||||
type: 'transcription',
|
type: 'transcription',
|
||||||
displayname: 'AssemblyAI',
|
displayname: 'AssemblyAI',
|
||||||
audioformat: "mp3",
|
|
||||||
|
|
||||||
async function(audioFileName) {
|
async function(audioFileName) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
@@ -116,9 +115,8 @@ module.exports = {
|
|||||||
resolve(saveTranscript(transcript, sessionId));
|
resolve(saveTranscript(transcript, sessionId));
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.error('Transcription error:', error.message);
|
console.error('Transcription error:', error.message);
|
||||||
reject(error);
|
reject(error);
|
||||||
return
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name:"Startup_function",
|
name:"Startup_function",
|
||||||
async function(){
|
async function(){
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -1,217 +0,0 @@
|
|||||||
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
|
|
||||||
Output ONLY the final .md document — no meta comments, no explanations.
|
|
||||||
|
|
||||||
Follow exactly the STRUCTURE defined below.
|
|
||||||
Follow exactly the STYLE rules.
|
|
||||||
Use timestamps in HH:MM:SS format.
|
|
||||||
If information is missing, use: Unclear:<reason>.
|
|
||||||
|
|
||||||
==================== STRUCTURE & RULES ====================
|
|
||||||
|
|
||||||
{
|
|
||||||
"FORMAT": "HTML",
|
|
||||||
|
|
||||||
"STRUCTURE": {
|
|
||||||
"titlepage": [
|
|
||||||
"title",
|
|
||||||
"date",
|
|
||||||
"start",
|
|
||||||
"end",
|
|
||||||
"duration",
|
|
||||||
"location",
|
|
||||||
"host",
|
|
||||||
"participants"
|
|
||||||
],
|
|
||||||
|
|
||||||
"toc": "[section](#anchor) — HH:MM:SS",
|
|
||||||
|
|
||||||
"section": {
|
|
||||||
"h2": "<topic> — HH:MM:SS",
|
|
||||||
"summary": "exactly 1 concise sentence",
|
|
||||||
"key_points": "maximum 5 bullet points; quotes optional",
|
|
||||||
"decisions": "list items formatted as: decision text | owner | due date",
|
|
||||||
"actions": "HTML table: id | task | owner | due | status"
|
|
||||||
},
|
|
||||||
|
|
||||||
"exec_summary": "exactly 3 short sentences",
|
|
||||||
|
|
||||||
"consolidated": [
|
|
||||||
"decisions",
|
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
|
|
||||||
"appendix": "optional"
|
|
||||||
},
|
|
||||||
|
|
||||||
"STYLE": {
|
|
||||||
"tone": "neutral, concise, professional",
|
|
||||||
"ts_format": "HH:MM:SS",
|
|
||||||
"no_meta": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROCESS": {
|
|
||||||
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
|
|
||||||
"speakers": "use names if available; else Speaker X",
|
|
||||||
"long_transcripts": "split → summarize → merge",
|
|
||||||
"unclear": "Unclear:<reason>"
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
|
|
||||||
}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Insert all generated content into the following HTML TEMPLATE:
|
|
||||||
|
|
||||||
# {{title}}
|
|
||||||
|
|
||||||
**Date:** {{date}}
|
|
||||||
**Start:** {{start}}
|
|
||||||
**End:** {{end}}
|
|
||||||
**Duration:** {{duration}}
|
|
||||||
**Location:** {{location}}
|
|
||||||
**Host:** {{host}}
|
|
||||||
**Participants:** {{participants}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
{{toc}}
|
|
||||||
|
|
||||||
---
|
|
||||||
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
|
|
||||||
Output ONLY the final .md document — no meta comments, no explanations.
|
|
||||||
|
|
||||||
Follow exactly the STRUCTURE defined below.
|
|
||||||
Follow exactly the STYLE rules.
|
|
||||||
Use timestamps in HH:MM:SS format.
|
|
||||||
If information is missing, use: UNKLAR:<reason>.
|
|
||||||
|
|
||||||
==================== STRUCTURE & RULES ====================
|
|
||||||
|
|
||||||
{
|
|
||||||
"FORMAT": "HTML",
|
|
||||||
|
|
||||||
"STRUCTURE": {
|
|
||||||
"titlepage": [
|
|
||||||
"title",
|
|
||||||
"date",
|
|
||||||
"start",
|
|
||||||
"end",
|
|
||||||
"duration",
|
|
||||||
"location",
|
|
||||||
"host",
|
|
||||||
"participants"
|
|
||||||
],
|
|
||||||
|
|
||||||
"toc": "[section](#anchor) — HH:MM:SS",
|
|
||||||
|
|
||||||
"section": {
|
|
||||||
"h2": "<topic> — HH:MM:SS",
|
|
||||||
"summary": "exactly 1 concise sentence",
|
|
||||||
"key_points": "maximum 5 bullet points; quotes optional",
|
|
||||||
"decisions": "list items formatted as: decision text | owner | due date",
|
|
||||||
"actions": "HTML table: id | task | owner | due | status"
|
|
||||||
},
|
|
||||||
|
|
||||||
"exec_summary": "exactly 3 short sentences",
|
|
||||||
|
|
||||||
"consolidated": [
|
|
||||||
"decisions",
|
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
|
|
||||||
"appendix": "optional"
|
|
||||||
},
|
|
||||||
|
|
||||||
"STYLE": {
|
|
||||||
"tone": "neutral, concise, professional",
|
|
||||||
"ts_format": "HH:MM:SS",
|
|
||||||
"no_meta": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROCESS": {
|
|
||||||
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
|
|
||||||
"speakers": "use names if available; else Speaker X",
|
|
||||||
"long_transcripts": "split → summarize → merge",
|
|
||||||
"unclear": "UNKLAR:<reason>"
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
|
|
||||||
}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Insert all generated content into the following HTML TEMPLATE:
|
|
||||||
|
|
||||||
# {{title}}
|
|
||||||
|
|
||||||
**Date:** {{date}}
|
|
||||||
**Start:** {{start}}
|
|
||||||
**End:** {{end}}
|
|
||||||
**Duration:** {{duration}}
|
|
||||||
**Location:** {{location}}
|
|
||||||
**Host:** {{host}}
|
|
||||||
**Participants:** {{participants}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
{{toc}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
{{exec_summary}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sections
|
|
||||||
{{sections}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Decisions
|
|
||||||
{{consolidated_decisions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Actions
|
|
||||||
{{consolidated_actions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix
|
|
||||||
{{appendix}}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Final Requirement:
|
|
||||||
Output ONLY the completed HTML meeting report.
|
|
||||||
## Executive Summary
|
|
||||||
{{exec_summary}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sections
|
|
||||||
{{sections}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Decisions
|
|
||||||
{{consolidated_decisions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Actions
|
|
||||||
{{consolidated_actions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix
|
|
||||||
{{appendix}}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Final Requirement:
|
|
||||||
Output ONLY the completed HTML meeting report.
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from app.main import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
def test_health():
|
||||||
|
response = client.get("/health")
|
||||||
|
assert response.status_code == 200
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
// DO NOT TOUCH THIS
|
|
||||||
require("../../requires.js")
|
|
||||||
|
|
||||||
mapFunctions = new Map()
|
|
||||||
// Loading the Function Map
|
|
||||||
var path = `${mainDir}/services/modules`
|
|
||||||
var folders = fs.readdirSync(path).filter(function (file) {
|
|
||||||
return fs.statSync(path+'/'+file).isDirectory();
|
|
||||||
});
|
|
||||||
folders.forEach(element => {
|
|
||||||
var commandFiles = fs.readdirSync(`${path}/${element}`).filter(file => file.endsWith('.js') && !file.startsWith("index"));
|
|
||||||
for (const file of commandFiles) {
|
|
||||||
delete require.cache[require.resolve(`${path}/${element}/${file}`)];
|
|
||||||
const command = require(`${path}/${element}/${file}`);
|
|
||||||
mapFunctions.set(command.name, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// You can touch beyond this point
|
|
||||||
|
|
||||||
let audiopath
|
|
||||||
let transcriptPath
|
|
||||||
let summarizePath
|
|
||||||
let llmpath
|
|
||||||
|
|
||||||
describe("Unit Tests", function() {
|
|
||||||
|
|
||||||
describe('Audio Extraction', function () {
|
|
||||||
this.slow(1000)
|
|
||||||
this.timeout(3000)
|
|
||||||
it('Extract .mp4 to .mp3', function (done) {
|
|
||||||
|
|
||||||
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "mp3"}).then(resp => {
|
|
||||||
audiopath = resp
|
|
||||||
// console.log(resp);
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('Extract .mp4 to .flac', function (done) {
|
|
||||||
|
|
||||||
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "flac"}).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('Extracting to a nonexistant format', function (done) {
|
|
||||||
|
|
||||||
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "qqq"}).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('Extracting from nonexistant file', function (done) {
|
|
||||||
|
|
||||||
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: "a", outputType: "mp3"}).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('Extracting from nonexistant file to nonexistant format', function (done) {
|
|
||||||
|
|
||||||
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: "a", outputType: "qqq"}).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("Audio Transcription", function() {
|
|
||||||
this.slow(20000)
|
|
||||||
this.timeout(120000)
|
|
||||||
|
|
||||||
it('Assembly', function (done) {
|
|
||||||
mapFunctions.get("assembly").function(audiopath).then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
transcriptPath = resp
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Assembly Wrong file', function (done) {
|
|
||||||
mapFunctions.get("assembly").function("a").then(resp => {
|
|
||||||
// console.log(resp);
|
|
||||||
// transcriptPath = resp
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
// console.log(err);
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// TODO add more Transcription Tool tests here
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Transcript Summarizer", function() {
|
|
||||||
this.slow(100)
|
|
||||||
this.timeout(1000)
|
|
||||||
|
|
||||||
it("Summarizer 1", function (done){
|
|
||||||
mapFunctions.get("summarize-transcription").function(transcriptPath).then(resp => {
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Summarizer 1 Wrong File", function (done){
|
|
||||||
mapFunctions.get("summarize-transcription").function("a").then(resp => {
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Summarizer 2 (Main)", function (done){
|
|
||||||
mapFunctions.get("summarize-transcription2").function(transcriptPath).then(resp => {
|
|
||||||
summarizePath = resp
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Summarizer 2 (Main) Wrong File", function (done){
|
|
||||||
mapFunctions.get("summarize-transcription2").function("a").then(resp => {
|
|
||||||
done("Didnt crash")
|
|
||||||
}).catch(err => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Large Language Model", function() {
|
|
||||||
this.slow(30000)
|
|
||||||
this.timeout(120000)
|
|
||||||
|
|
||||||
// it("ChatGPT", function (done){
|
|
||||||
// mapFunctions.get("chatgpt").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
|
|
||||||
// done()
|
|
||||||
// }).catch(err => {
|
|
||||||
// throw err
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
it("Gemini", function (done){
|
|
||||||
mapFunctions.get("llm-gemini").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
|
|
||||||
llmpath = resp
|
|
||||||
done()
|
|
||||||
}).catch(err => {
|
|
||||||
throw err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
after(function() {
|
|
||||||
console.log(`\n\n\n${audiopath} \n${transcriptPath} \n${summarizePath} \n${llmpath}`);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Reference in New Issue
Block a user