mirror of
https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
synced 2026-06-15 18:01:52 +02:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| df5ac8913d | |||
| 9696434145 | |||
| 9fc44bea63 | |||
| b6f887466b | |||
| e40be401c8 | |||
| 1f96d90a2d | |||
| 33ce22ec45 | |||
| b9f3967b61 | |||
| 8cd654bcbc | |||
| 6b3724b765 | |||
| 5a85a7da4c | |||
| 80eb9dac23 | |||
| 11f7db1b1c | |||
| 947e981ac0 | |||
| bef9c44a2f | |||
| 60b9f8a3b9 | |||
| 4dd7b512a1 | |||
| d21bbbce12 | |||
| 7bce7c8d36 | |||
| 3c3d7a1d3e | |||
| 1c85272abc | |||
| 18b624736d | |||
| 6c41da781e | |||
| 9b8561e4ce | |||
| 39af2c3312 | |||
| 9ad335d872 | |||
| c833d5bb74 | |||
| 7647398974 | |||
| 43e21cfd8d | |||
| 4c1897741f | |||
| f3cc6b5798 | |||
| 7e4cf93cae | |||
| fe86fa1a2f | |||
| 1e4bde93b1 | |||
| c62ee5aa41 | |||
| 0a5fa79668 | |||
| 30b94c4e62 | |||
| cc883905bc | |||
| 40edcaa69d | |||
| c7625e5713 | |||
| f5c2e2700b | |||
| 9c156a7df3 | |||
| ee31d26116 | |||
| a13fea6734 | |||
| e82cf779da |
Binary file not shown.
@@ -0,0 +1,116 @@
|
||||
# Documenation of our Program
|
||||
|
||||
## Table of Contents
|
||||
1. [How to run the Software](#how-to-run-the-software)
|
||||
2. [How it works](#how-it-works)
|
||||
3. [Modules](#modules)
|
||||
3. [IPC](#ipc)
|
||||
|
||||
## How to run the Software
|
||||
If you read the readme file, you will see the basic setup command in order to run the program.
|
||||
You will need nodejs, the newer the better.
|
||||
The software is tested with `nodejs-19`, `nodejs-20`, `nodejs-22` and `nodejs-24`.
|
||||
These versions are confirmed to work with our software, but prior versions may work aswell.
|
||||
To get nodejs, simply go to their [website](https://nodejs.org/en/download) and download whatever version you want and install it.
|
||||
Afterward go into the directory of our program, and run the command `npm i`, this will install all the necessary libraries.
|
||||
Next up you need to set up the .env file.
|
||||
The file must contain your keys for the modules you want to use.
|
||||
The .env file looks like this:
|
||||
```
|
||||
ASSEMBLYAI_API_KEY=wefhjhjakeghjkahejkghjkaegh
|
||||
GOOGLE_API_KEY=wefhjhjakeghjkahejkghjkaegh
|
||||
SAIA_API_KEY=wefhjhjakeghjkahejkghjkaegh
|
||||
```
|
||||
Note that if you write your module in the same format we did, then you will only need to supply the api keys to the individual services you will actually use.
|
||||
If you dont want to use Assembly AI, you can for example just leave this row out of your .env, and the program will just work fine.
|
||||
Only issue will be that it will throw an error if you do run the Assembly AI module anyways.
|
||||
Once that is done, you can run the command `npm start` to actually start the program.
|
||||
Alternatively you can double click the start.bat if you are on Windows for example.
|
||||
|
||||
## How it works
|
||||
Our software is fully modular, this means, every part can easily be edited, replaced, removed or added without needing to make many adjustments in the code.
|
||||
The modules can be found under `./services/modules`
|
||||
The Structure is as follows:
|
||||
Inside of `modules` are folders named after the general thing the module does.
|
||||
For example, `transcription-remote`, this folder contains all the modules that do transcription on a remote service, such as assembly-ai for example.
|
||||
Inside of these folders we put our modules.
|
||||
The name of the folder and the module dont matter, as long as the structure is kept, and the module filename ends with .js, it will work.
|
||||
The program iterates through all of the folders within `./services/modules`, and then iterates over each `.js` file within each of these folders, and then loads them into a specific map called `mapFunctions`.
|
||||
This map is available ANYWHERE in the backend code, even within a module, which means, you can call a module, from within a module, from within a module, from within yet another module.
|
||||
|
||||
## Modules
|
||||
Building a new module is super easy, any idiot can get it done.
|
||||
All you need to do is follow the previously mentioned structure.
|
||||
When you have created your module file, the `.js` file, you simply copy paste this code snippet into it.
|
||||
```js
|
||||
module.exports = {
|
||||
name:"example", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()"
|
||||
type:"example-type", // value used to differentiate each module to order them in the UI
|
||||
displayname:"Example", // The displayname used within the UI
|
||||
async function(randomParameter){
|
||||
// Here we put a simple console.log to show how the system works
|
||||
// This function will be called from the @startup.js function in the utility folder
|
||||
console.log(`\n------------\nThis is the example function called by the ${randomParameter} function\n------------\n`);
|
||||
}
|
||||
}
|
||||
```
|
||||
If by this point, you cared enough to actually look at the code and the modules and so on, you might have spotted a file in `./services/modules/utility` called `example.js`.
|
||||
This is a template file that you can just copy paste and use as a base for your new module.
|
||||
It has the same exact code as mentioned right above.
|
||||
Now as for how the code works.
|
||||
Each module is essentially just a JSON object that is being exported, so that the main process can load it into the `mapFunctions` map.
|
||||
the required fields are as follows
|
||||
- name: This field contains the internal name through which it will be called. It HAS TO BE unique.
|
||||
- type: This field contains the type of the module. Is it an LLM module, transcription module, or whatever.
|
||||
- displayname: This field contains the Displayname used in the UI.
|
||||
|
||||
And lastly the function call.
|
||||
This function call is what is being called by other functions, it is generally the main entrypoint for a module.
|
||||
Sure, you can always set custom function names, but this is a general solution that works without having to manage function names.
|
||||
You can always define custom functions inside your module that you call from the entrypoint function, but it is highly advised just to call the entrypoint function from outside of the module as it prevents headaches by just working as intended.
|
||||
|
||||
Note, there are also other module fields for specific module types, such as:
|
||||
- description: Used by any module that needs to be shown on the UI, such as Transcription and LLM modules.
|
||||
- audioformat: Used by transcription modules to tell the audio extraction module what audio format to use.
|
||||
|
||||
## IPC
|
||||
Our software is split up into 2 pieces, the main process (Backend) and the frontend.
|
||||
The frontend is written in Electron, so it is essentially just a website.
|
||||
This makes it relatively easy to edit the frontend.
|
||||
But it comes with one downside, which is, the frontend and backend cant just directly communicate, you first need to set up an IPC channel between them.
|
||||
As for the base functionality, all of this is already done.
|
||||
The frontend gets a list of all the available LLM and Transcription modules sent by the backend on startup.
|
||||
The JSON object for this information looks like this:
|
||||
```json
|
||||
{
|
||||
"ai_modules":[
|
||||
{"name": "Example", "displayname": "Example"}
|
||||
],
|
||||
"transcription_modules":[
|
||||
{"name": "Example", "displayname": "Example"}
|
||||
]
|
||||
}
|
||||
```
|
||||
The backend needs a specific set of informations from the frontend in order to start the pipeline.
|
||||
The JSON for that looks like this:
|
||||
```json
|
||||
{
|
||||
"video": {
|
||||
"module": "extraction-video-to-audio",
|
||||
"inputVideoPath": "A:\\programing\\@projects\\video2document\\test\\unit\\testvideo.mp4"
|
||||
},
|
||||
"transcription": {
|
||||
"module": "assembly"
|
||||
},
|
||||
"document": {
|
||||
"module": "llm-saia_openai_gpt",
|
||||
"type": "followup-report",
|
||||
"outputType": "pdf"
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see in this JSON object, each part specifies which module is being used for each step.
|
||||
The module names are each the name field specified in the module itself.
|
||||
As for the rest of the fields, they are pretty self explanatory except `document.type`, that is a predefined report type.
|
||||
This is the minimum required setup for the currently implemented pipeline to work.
|
||||
You can always add fields to it, but dont remove the ones from above.
|
||||
@@ -6,242 +6,11 @@
|
||||
<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: center;
|
||||
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;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
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>Manage document types</h1>
|
||||
|
||||
<label for="existingDocs">Vorhandene Dokumente auswählen (optional):</label>
|
||||
<!--Drop Down-->
|
||||
<select name="existingDocs" id="existingDocs">
|
||||
<option value="newDoc">-- Neues Dokument erstellen --</option>
|
||||
</select>
|
||||
|
||||
<div id="docNameWrapper">
|
||||
<label for="docName">Dokumentname:</label>
|
||||
<input type="text" id="docName" placeholder="Gib hier den Dokumentnamen ein">
|
||||
</div>
|
||||
|
||||
<label for="prompt">Dein Prompt:</label>
|
||||
<textarea id="prompt" placeholder="Schreibe hier den Prompt für dein Dokument..."></textarea>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="index.html">
|
||||
<button id="goBackBtn">Abbrechen</button>
|
||||
</a>
|
||||
<button id="deleteBtn">Dokument löschen</button>
|
||||
<button id="generateBtn">Dokument speichern</button>
|
||||
</div>
|
||||
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
|
||||
<script src="languages.js"></script>
|
||||
<script>
|
||||
const goBackBtn = document.getElementById("goBackBtn");
|
||||
const generateBtn = document.getElementById("generateBtn");
|
||||
const deleteBtn = document.getElementById("deleteBtn");
|
||||
const existingDocs = document.getElementById("existingDocs");
|
||||
const docNameInput = document.getElementById("docName");
|
||||
const promptInput = document.getElementById("prompt");
|
||||
const resultDiv = document.getElementById("result");
|
||||
const exampleText = "";
|
||||
|
||||
// dokumente speichern
|
||||
generateBtn.addEventListener("click", () => {
|
||||
const name = docNameInput.value.trim();
|
||||
const content = promptInput.value.trim();
|
||||
if (!name || !content) {
|
||||
resultDiv.textContent = "Bitte Dokumentname und Prompt ausfüllen.";
|
||||
setTimeout(() => {
|
||||
resultDiv.textContent = "";
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
window.api.saveTxtFile(name, content).then();
|
||||
resultDiv.textContent = "Dokument erfolgreich gespeichert!";
|
||||
setTimeout(() => {
|
||||
resultDiv.textContent = "";
|
||||
}, 3000);
|
||||
reloadDocuments();
|
||||
|
||||
});
|
||||
|
||||
// dokumente löschen
|
||||
deleteBtn.addEventListener("click", () => {
|
||||
const name = docNameInput.value.trim();
|
||||
|
||||
if (!name) {
|
||||
resultDiv.textContent = "Bitte Dokumentname angeben.";
|
||||
setTimeout(() => {
|
||||
resultDiv.textContent = "";
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmDelete = confirm(
|
||||
`Möchtest du das Dokument "${name}" wirklich löschen?`
|
||||
);
|
||||
|
||||
if (!confirmDelete) return;
|
||||
|
||||
window.api.deleteTxtFile(name).then((success) => {
|
||||
if (success) {
|
||||
resultDiv.textContent = "Dokument erfolgreich gelöscht!";
|
||||
reloadDocuments();
|
||||
existingDocs.value = "newDoc";
|
||||
existingDocs.dispatchEvent(new Event("change"));
|
||||
} else {
|
||||
resultDiv.textContent = "Dokument konnte nicht gelöscht werden.";
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
resultDiv.textContent = "";
|
||||
}, 3000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//function to load existingDoc options to the drop down list
|
||||
const select = document.getElementById('existingDocs');
|
||||
|
||||
window.api.getTxtFiles().then(files => {
|
||||
reloadDocuments();
|
||||
});
|
||||
|
||||
//content anzeigen
|
||||
const docNameWrapper = document.getElementById("docNameWrapper");
|
||||
|
||||
existingDocs.addEventListener("change", async () => {
|
||||
const selected = existingDocs.value;
|
||||
|
||||
if (selected === "newDoc") {
|
||||
docNameWrapper.classList.remove("hidden");
|
||||
docNameInput.value = "";
|
||||
promptInput.value = exampleText;
|
||||
return;
|
||||
}
|
||||
docNameWrapper.classList.add("hidden");
|
||||
|
||||
const content = await window.api.readTxtFile(selected);
|
||||
promptInput.value = content;
|
||||
docNameInput.value = selected.replace(".txt", "");
|
||||
});
|
||||
|
||||
//reload drop down
|
||||
function reloadDocuments() {
|
||||
[...existingDocs.querySelectorAll('option:not([value="newDoc"])')]
|
||||
.forEach(o => o.remove());
|
||||
|
||||
window.api.getTxtFiles().then(files => {
|
||||
files.forEach(file => {
|
||||
const option = document.createElement('option');
|
||||
option.value = file;
|
||||
option.textContent = file
|
||||
.replace('.txt', '') // Endung entfernen
|
||||
.replace(/_/g, ' ') // Leerzeichen ersetzen
|
||||
.replace(/\b\w/g, c => c.toUpperCase()) // ersten Buchstaben groß
|
||||
existingDocs.appendChild(option);
|
||||
//customDocumentTypes.appendChild(option);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="./renderer.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
+64
-15
@@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title id="title">Video to document</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/themes/light.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -19,30 +20,66 @@
|
||||
</label>
|
||||
|
||||
<nav class="menu1">
|
||||
<a href="custom_document.html" class="li1">Manage document types</a>
|
||||
<button id="customDocBtn" onclick="showCD()">Manage document types</button>
|
||||
<a href="help_page.html" class="li1">Help</a>
|
||||
</nav>
|
||||
</nav>
|
||||
</section>
|
||||
|
||||
<h1 id="h1">Video to document</h1>
|
||||
|
||||
<div class="gui-language">
|
||||
<!-- to do: Ausprobieren mit li, a oder button, im Notfall ohne Flaggen Icons, kein hover-->
|
||||
<select name="language_option" id="language_option"></select>
|
||||
</div>
|
||||
|
||||
</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 class="step-item active" data-step="1" id="step_nav1">1. Step</div>
|
||||
<div class="step-item" data-step="2" id="step_nav2">2. Step</div>
|
||||
<div class="step-item" data-step="3" id="step_nav3">3. Step</div>
|
||||
<div class="step-item" data-step="4" id="step_nav4">4. Step</div>
|
||||
<div class="step-item" data-step="5" id="step_nav5">5. Step</div>
|
||||
<div class="step-item" data-step="6" id="step_nav6">6. Step</div>
|
||||
</div>
|
||||
|
||||
<div id="middleContainerWrapper" class="middle-container-wrapper">
|
||||
<button id="prevBtn" class="navBtn" disabled>←</button>
|
||||
|
||||
<!-- Visible middle part-->
|
||||
<div class="mitte" id="mitte">
|
||||
|
||||
<!--Costum document section-->
|
||||
<div class="container" id="cdContainer" style="display:none;">
|
||||
<h1 id="cd_h1">Manage document types</h1>
|
||||
|
||||
<label for="existingDocs" id="cd_existingDocs">Select existing documents (optional):</label>
|
||||
<!--Drop Down-->
|
||||
<select name="existingDocs" id="existingDocs">
|
||||
<option value="newDoc" id="newDoc">-- Create new document --</option>
|
||||
</select>
|
||||
|
||||
<div id="docNameWrapper">
|
||||
<label for="docName" id="cd_docName">Document name:</label>
|
||||
<input type="text" id="docName" placeholder="Enter the document name here">
|
||||
</div>
|
||||
|
||||
<label for="prompt" id="cd_promt">Your prompt:</label>
|
||||
<textarea id="prompt" placeholder="Type the prompt for your document here..."></textarea>
|
||||
|
||||
<div class="buttons">
|
||||
<button id="goBackBtn">Return</button>
|
||||
<button id="deleteBtn">Delete document</button>
|
||||
<button id="generateBtn">Save document</button>
|
||||
</div>
|
||||
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 1-->
|
||||
<div class="step" id="step1">
|
||||
<h2 class="h2">Upload your video here:</h2>
|
||||
<div class="upload-container" id="uploadContainer">
|
||||
<p id="p1">Drag and drop video file</p>
|
||||
<video id="previewThumbnail" autoplay="false">
|
||||
@@ -56,7 +93,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 2-->
|
||||
<div class="step" id="step2" style="display:none;">
|
||||
<h2 class="h2">Choose your preferences:</h2>
|
||||
<div class="KI-wrapper">
|
||||
<label id="labelKI">Select ki:</label>
|
||||
<select name="ai_type" id="ai_type"></select>
|
||||
@@ -78,15 +117,19 @@
|
||||
|
||||
<div class="language-wrapper">
|
||||
<label id="labelLanguage">Select language:</label>
|
||||
<img id="labelLanguageFlag" src="flags/united-kingdom-flag-png-large.jpg" width="20" height="10" >
|
||||
<select name="language_option" id="language_option">
|
||||
|
||||
<select name="document_language_option" id="document_language_option">
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 3-->
|
||||
|
||||
<!-- Hover Effekt für Dokumentenvorschau, Fragezeichen hinter Text, drüber hoven zeigt Beispieldokument -->
|
||||
<div class="step" id="step3" style="display:none;">
|
||||
<div class="checkbox-group">
|
||||
<label id="checkbox-label" for="checkbox-group">Choose prefered document style:</label>
|
||||
<h2 class="h2">Choose prefered document style:</h2>
|
||||
<div class="checkbox-container">
|
||||
<input type="checkbox" name ="docFormat" id="docFormat" value="followup-report">
|
||||
<label id="label_format" for="docFormat">Follow-up Report</label>
|
||||
@@ -111,32 +154,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 4-->
|
||||
<div class="step" id="step4" style="display:none;">
|
||||
<h2 class="h2">Klick to submit:</h2>
|
||||
<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>
|
||||
<p id="box1_p1">---Starting---</p>
|
||||
<div class="box2" id="box2">
|
||||
</div>
|
||||
<p>---Transkribing---</p>
|
||||
<p id="box2_p2">---Transkribing---</p>
|
||||
<div class="box2" id="box3">
|
||||
</div>
|
||||
<p>---Document creation---</p>
|
||||
<p id="box3_p3">---Document creation---</p>
|
||||
<div class="box2" id="box4">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 5-->
|
||||
<div class="step" id="step5" style="display:none;">
|
||||
<h2 class="h2">Change names of the speakers:</h2>
|
||||
<div class="speakerView" id="speakerView">
|
||||
<label id="labelSpeaker">Select Speaker:</label>
|
||||
<select name="cur_speaker" id="cur_speaker">
|
||||
</select>
|
||||
</div>
|
||||
<div class="speakerAudio" id="speakerAutio">
|
||||
<label id="labelSpeakerAudio">Selected Speaker</label>
|
||||
<label id="labelSpeakerAudio">Selected Speaker:</label>
|
||||
<audio controls id="speakerAudioViewer">
|
||||
Currently there is no audio file here.
|
||||
</audio>
|
||||
@@ -151,7 +198,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here starts code from step 6-->
|
||||
<div class="step" id="step6" style="display:none;">
|
||||
<h2 class="h2">Klick to download your document:</h2>
|
||||
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,7 +208,7 @@
|
||||
<button id ="nextBtn" class="navBtn">→</button>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/lc-select@1.3.0/lc_select.min.js"></script>
|
||||
<script src="languages.js"></script>
|
||||
<script src="script.js"></script>
|
||||
<script src="./renderer.js"></script>
|
||||
|
||||
@@ -12,7 +12,37 @@ var languageOptions = {
|
||||
"checkbox_group": "Choose prefered document style:",
|
||||
"label_format": "Meeting report",
|
||||
"label_summary": "Summary with timestamps",
|
||||
"submitButton": "Submit"
|
||||
"submitButton": "Submit",
|
||||
"step_nav1": "Step 1",
|
||||
"step_nav2": "Step 2",
|
||||
"step_nav3": "Step 3",
|
||||
"step_nav4": "Step 4",
|
||||
"step_nav5": "Step 5",
|
||||
"step_nav6": "Step 6",
|
||||
"h2": "Upload your video here:",
|
||||
"labelSpeaker": "Select Speaker:",
|
||||
"labelSpeakerAudio": "Selected Speaker:",
|
||||
"labelSpeakerWriter": "Write name:",
|
||||
"speakerLocker": "Rename speaker",
|
||||
"speakerResender": "Rewrite document",
|
||||
"downloadButton": "Download",
|
||||
"box1_p1": "---Starting---",
|
||||
"box2_p2": "---Transkribing---",
|
||||
"box3_p3": "---Document creation---",
|
||||
"labelType": "Select document type:",
|
||||
|
||||
"customDocBtn": "Manage document types",
|
||||
"cd_h1": "Manage document types",
|
||||
"cd_existingDocs": "Select existing documents (optional):",
|
||||
"cd_docName": "Document name",
|
||||
"docName": "Enter the document name here",
|
||||
"cd_promt": "Your prompt:",
|
||||
"prompt": "Type the prompt for your document here...",
|
||||
"goBackBtn": "Return",
|
||||
"deleteBtn": "Delete document",
|
||||
"generateBtn": "Save document",
|
||||
"newDoc": "-- Create new document --"
|
||||
|
||||
},
|
||||
"de":{
|
||||
"flagPath": "flags/germany-flag-png-large.jpg",
|
||||
@@ -27,7 +57,36 @@ var languageOptions = {
|
||||
"checkbox_group": "Bevorzugte Dokumentvarianten:",
|
||||
"label_format": "Meeting Bericht",
|
||||
"label_summary": "Zusammenfassung mit Zeitstempeln",
|
||||
"submitButton": "Absenden"
|
||||
"submitButton": "Absenden",
|
||||
"step_nav1": "Schritt 1",
|
||||
"step_nav2": "Schritt 2",
|
||||
"step_nav3": "Schritt 3",
|
||||
"step_nav4": "Schritt 4",
|
||||
"step_nav5": "Schritt 5",
|
||||
"step_nav6": "Schritt 6",
|
||||
"h2": "Uploade dein Video hier:",
|
||||
"labelSpeaker": "Wähle Sprecher:",
|
||||
"labelSpeakerAudio": "Ausgewählter Sprecher:",
|
||||
"labelSpeakerWriter": "Schreib Namen:",
|
||||
"speakerLocker": "Ersetze Namen",
|
||||
"speakerResender": "Überschreibe Dokument",
|
||||
"downloadButton": "Download",
|
||||
"box1_p1": "---Startet---",
|
||||
"box2_p2": "---Transkribing---",
|
||||
"box3_p3": "---Dokument kreieren---",
|
||||
"labelType": "Wähle Dokumenttype:",
|
||||
|
||||
"customDocBtn": "Dokumenttypen verwalten",
|
||||
"cd_h1": "Dokumenttypen verwalten",
|
||||
"cd_existingDocs": "Vorhandene Dokumente auswählen (optional):",
|
||||
"cd_docName": "Dokument Name",
|
||||
"docName": "Geben Sie hier den Dokumentnamen ein",
|
||||
"cd_promt": "Ihr Prompt:",
|
||||
"prompt": "Geben Sie hier die Eingabeaufforderung für Ihr Dokument ein...",
|
||||
"goBackBtn": "Zurück",
|
||||
"deleteBtn": "Lösche Dokument",
|
||||
"generateBtn": "Speicher Dokument",
|
||||
"newDoc": "-- Neues Dokument erstellen --"
|
||||
},
|
||||
"in":{
|
||||
"flagPath": "flags/india-flag-png-large.png",
|
||||
@@ -42,7 +101,37 @@ var languageOptions = {
|
||||
"checkbox_group": "पसंदीदा दस्तावेज़ शैली चुनें:",
|
||||
"label_format": "बैठक रिपोर्ट",
|
||||
"label_summary": "टाइमस्टैम्प के साथ सारांश",
|
||||
"submitButton": "जमा करना"
|
||||
"submitButton": "जमा करना",
|
||||
"step_nav1": "स्टेप 1",
|
||||
"step_nav2": "स्टेप 2",
|
||||
"step_nav3": "स्टेप 3",
|
||||
"step_nav4": "स्टेप 4",
|
||||
"step_nav5": "स्टेप 5",
|
||||
"step_nav6": "स्टेप 6",
|
||||
"h2": "अपना वीडियो यहां अपलोड करें:",
|
||||
"labelSpeaker": "स्पीकर चुनें:",
|
||||
"labelSpeakerAudio": "चयनित वक्ता:",
|
||||
"labelSpeakerWriter": "नाम लिखें:",
|
||||
"speakerLocker": "स्पीकर का नाम बदलें",
|
||||
"speakerResender": "दस्तावेज़ पुनः लिखें",
|
||||
"downloadButton": "डाउनलोड करना",
|
||||
"box1_p1": "---प्रारंभ---",
|
||||
"box2_p2": "---प्रतिलेखन---",
|
||||
"box3_p3": "---दस्तावेज़ निर्माण---",
|
||||
"labelType": "दस्तावेज़ प्रकार चुनें:",
|
||||
|
||||
"customDocBtn": "दस्तावेज़ प्रकार प्रबंधित करें",
|
||||
"cd_h1": "दस्तावेज़ प्रकार प्रबंधित करें",
|
||||
"cd_existingDocs": "मौजूदा दस्तावेज़ों का चयन करें (वैकल्पिक):",
|
||||
"cd_docName": "दस्तावेज़ का नाम",
|
||||
"docName": "यहां दस्तावेज़ का नाम दर्ज करें",
|
||||
"cd_promt": "आपका संकेत:",
|
||||
"prompt": "अपने दस्तावेज़ के लिए प्रॉम्प्ट यहां टाइप करें...",
|
||||
"goBackBtn": "वापस करना",
|
||||
"deleteBtn": "दस्तावेज़ हटाएँ",
|
||||
"generateBtn": "दस्तावेज़ सहेजें",
|
||||
"newDoc": "-- नया दस्तावेज़ बनाएँ --"
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
+270
-122
@@ -1,58 +1,102 @@
|
||||
/*
|
||||
|
||||
uploadContainer.addEventListener("dragover", (e) =>{
|
||||
Listeners for the program setup and changes
|
||||
|
||||
*/
|
||||
|
||||
//Listener for when the gui has been loaded so it can fill the dop down menus in step 2 and the language options
|
||||
window.addEventListener('load', async (e) => {
|
||||
try {
|
||||
loadLanguageOptions();
|
||||
const value = await window.onStartup.getModuleNames();
|
||||
loadAiOptions(value.ai_modules);
|
||||
loadTranscriptionOptions(value.transcription_modules);
|
||||
|
||||
} catch (error) {
|
||||
console.log("Error in the window listener load in the renderer.js \n");
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
//Listener if the language of the displayed text's in the gui should be changed
|
||||
language_option.addEventListener('change', (e) => {
|
||||
try {
|
||||
const select = document.getElementById('language_option');
|
||||
changeLanguage(select.value);
|
||||
} catch (error) {
|
||||
console.log("Error in the language_option change listener in the renderer.js");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
stepButtons.forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
try {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const step = parseInt(btn.dataset.step);
|
||||
showStep(step);
|
||||
} catch (error) {
|
||||
console.log("Error in renderer.js dragover listener function")
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
//Listener if the button to change the current step to the previus one is pressed
|
||||
prevBtn.addEventListener("click", () => {
|
||||
try {
|
||||
if (currentStep > 1) showStep(currentStep - 1);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
//Listener if the button to change the current step to the next one is pressed
|
||||
nextBtn.addEventListener("click", () => {
|
||||
try {
|
||||
if (currentStep < totalSteps) showStep(currentStep + 1);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
Listeners for Step 1
|
||||
|
||||
*/
|
||||
|
||||
//Listener if a file has been draged over the drop down field
|
||||
uploadContainer.addEventListener("dragover", (e) => {
|
||||
try {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
} catch (error) {
|
||||
console.log("Error in renderer.js dragover listener function")
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//listener for when a file get dropped on the drag&drop field
|
||||
uploadContainer.addEventListener("drop", (e) => {
|
||||
try {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const files = e.dataTransfer.files
|
||||
const filePath = window.explorer.onFileDrop(files[0])
|
||||
const testEndings = [".mp4", ".mov", ".avi", ".mkv"];
|
||||
var pathToLower = filePath.toLowerCase();
|
||||
if(testEndings.some(e => pathToLower.endsWith(e))){
|
||||
const files1 = e.dataTransfer.files;
|
||||
handleFiles(files1);
|
||||
}else{
|
||||
alert('The given file is not compatible. These are the available types: [".mp4", ".mov", ".avi", ".mkv"].');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log("Error in renderer.js with the listerner for the drop function");
|
||||
console.log(error);
|
||||
}
|
||||
})
|
||||
|
||||
window.addEventListener('load', async (e) => {
|
||||
try {
|
||||
loadLanguageOptions();
|
||||
const value = await window.onStartup.getModuleNames();
|
||||
loadAiOptions(value.ai_modules);
|
||||
loadTranscriptionOptions(value.transcription_modules);
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const files = e.dataTransfer.files
|
||||
const filePath = window.explorer.onFileDrop(files[0])
|
||||
const testEndings = [".mp4", ".mov", ".avi", ".mkv"];
|
||||
var pathToLower = filePath.toLowerCase();
|
||||
if (testEndings.some(e => pathToLower.endsWith(e))) {
|
||||
const files1 = e.dataTransfer.files;
|
||||
handleFiles(files1);
|
||||
} else {
|
||||
alert('The given file is not compatible. These are the available types: [".mp4", ".mov", ".avi", ".mkv"].');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
console.log("Error in renderer.js with the listerner for the drop function");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
language_option.addEventListener('change', (e)=>{
|
||||
try {
|
||||
const select = document.getElementById('language_option');
|
||||
changeLanguage(select.value);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
//listener for the file explorer search when something got selected
|
||||
videoUpload.addEventListener("change", () => {
|
||||
@@ -74,170 +118,274 @@ manualUploadBtn.addEventListener('click', () => {
|
||||
console.log("Error in manualBtn EventListener click");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
stepButtons.forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
try {
|
||||
const step = parseInt(btn.dataset.step);
|
||||
showStep(step);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
/*
|
||||
|
||||
Listeners for Step 2
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Listeners for Step 3
|
||||
|
||||
*/
|
||||
|
||||
window.api.getTxtFiles().then(files => {
|
||||
var menu = document.getElementById('customDocumentTypes');
|
||||
var l = document.getElementById('customDocumentTypes').options.length - 1;
|
||||
for (i = l; i >= 0; i--) {
|
||||
menu.remove(i);
|
||||
}
|
||||
files.forEach(file => {
|
||||
const option = document.createElement('option');
|
||||
option.value = file;
|
||||
option.textContent = file
|
||||
.replace('.txt', '') // Endung entfernen
|
||||
.replace(/_/g, ' ') // Leerzeichen ersetzen
|
||||
.replace(/\b\w/g, c => c.toUpperCase()) // ersten Buchstaben groß
|
||||
menu.appendChild(option);
|
||||
});
|
||||
});
|
||||
|
||||
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) =>{
|
||||
docFormat.addEventListener("change", (e) => {
|
||||
try {
|
||||
if(docFormat.checked){
|
||||
if (docFormat.checked) {
|
||||
docFormatSummary1.checked = false;
|
||||
docFormatSummary2.checked = false;
|
||||
docFormatSummary3.checked = false;
|
||||
docFormatCustom.checked = false;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
docFormatSummary1.addEventListener("change", (e) =>{
|
||||
docFormatSummary1.addEventListener("change", (e) => {
|
||||
try {
|
||||
if(docFormatSummary1.checked){
|
||||
if (docFormatSummary1.checked) {
|
||||
docFormat.checked = false;
|
||||
docFormatSummary2.checked = false;
|
||||
docFormatSummary3.checked = false;
|
||||
docFormatCustom.checked = false;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
docFormatSummary2.addEventListener("change", (e) =>{
|
||||
docFormatSummary2.addEventListener("change", (e) => {
|
||||
try {
|
||||
if(docFormatSummary2.checked){
|
||||
if (docFormatSummary2.checked) {
|
||||
docFormatSummary1.checked = false;
|
||||
docFormat.checked = false;
|
||||
docFormatSummary3.checked = false;
|
||||
docFormatCustom.checked = false;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
docFormatSummary3.addEventListener("change", (e) =>{
|
||||
docFormatSummary3.addEventListener("change", (e) => {
|
||||
try {
|
||||
if(docFormatSummary3.checked){
|
||||
if (docFormatSummary3.checked) {
|
||||
docFormatSummary1.checked = false;
|
||||
docFormatSummary2.checked = false;
|
||||
docFormat.checked = false;
|
||||
docFormatCustom.checked = false;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
docFormatCustom.addEventListener("change", (e) =>{
|
||||
docFormatCustom.addEventListener("change", (e) => {
|
||||
try {
|
||||
if(docFormatCustom.checked){
|
||||
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 = speakerAudios[document.getElementById("cur_speaker").value].src;
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
});
|
||||
/*
|
||||
|
||||
window.audios.speakerAudios((event, arg) => {
|
||||
loadSpeakerOptions(arg);
|
||||
setSpeakerAudiosValue(arg);
|
||||
});
|
||||
Listeners for Step 4
|
||||
|
||||
*/
|
||||
//Functions the the displayed progress in the progressbar can be changed out of the main process
|
||||
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();
|
||||
}
|
||||
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(){
|
||||
function setCircleOne() {
|
||||
try {
|
||||
if(document.getElementById("box1").style.backgroundColor == "green"){
|
||||
if (document.getElementById("box1").style.backgroundColor == "green") {
|
||||
document.getElementById("box1").style.backgroundColor = "red";
|
||||
}else{
|
||||
} else {
|
||||
document.getElementById("box1").style.backgroundColor = "green";
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
|
||||
};
|
||||
function setCircleZwo(){
|
||||
function setCircleZwo() {
|
||||
try {
|
||||
if(document.getElementById("box2").style.backgroundColor == "green"){
|
||||
if (document.getElementById("box2").style.backgroundColor == "green") {
|
||||
document.getElementById("box2").style.backgroundColor = "red";
|
||||
}else{
|
||||
} else {
|
||||
document.getElementById("box2").style.backgroundColor = "green";
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
function setCircleThree(){
|
||||
function setCircleThree() {
|
||||
try {
|
||||
if(document.getElementById("box3").style.backgroundColor == "green"){
|
||||
if (document.getElementById("box3").style.backgroundColor == "green") {
|
||||
document.getElementById("box3").style.backgroundColor = "red";
|
||||
}else{
|
||||
} else {
|
||||
document.getElementById("box3").style.backgroundColor = "green";
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
function setCircleFour(){
|
||||
function setCircleFour() {
|
||||
try {
|
||||
if(document.getElementById("box4").style.backgroundColor == "green"){
|
||||
if (document.getElementById("box4").style.backgroundColor == "green") {
|
||||
document.getElementById("box4").style.backgroundColor = "red";
|
||||
}else{
|
||||
} else {
|
||||
document.getElementById("box4").style.backgroundColor = "green";
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Listeners for Step 5
|
||||
|
||||
*/
|
||||
|
||||
//Speaker change listener
|
||||
cur_speaker.addEventListener("change", (e) => {
|
||||
try {
|
||||
document.getElementById("speakerAudioViewer").src = speakerAudios[document.getElementById("cur_speaker").value].src;
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
});
|
||||
//Function so the main process can give the gui a json with the speakers and their audio
|
||||
window.audios.speakerAudios((event, arg) => {
|
||||
loadSpeakerOptions(arg);
|
||||
setSpeakerAudiosValue(arg);
|
||||
});
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Listeners for the costum documents section
|
||||
|
||||
*/
|
||||
|
||||
goBackBtn.addEventListener("click", () => {
|
||||
showCD();
|
||||
});
|
||||
|
||||
// dokumente speichern
|
||||
generateBtn.addEventListener("click", () => {
|
||||
const name = docName.value.trim();
|
||||
const content = document.getElementById("prompt").value.trim();
|
||||
if (!name || !content) {
|
||||
result.textContent = "Bitte Dokumentname und Prompt ausfüllen.";
|
||||
console.log(name + " " + content);
|
||||
setTimeout(() => {
|
||||
result.textContent = "";
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
window.api.saveTxtFile(name, content).then();
|
||||
result.textContent = "Dokument erfolgreich gespeichert!";
|
||||
setTimeout(() => {
|
||||
result.textContent = "";
|
||||
}, 3000);
|
||||
reloadDocuments();
|
||||
|
||||
});
|
||||
|
||||
// dokumente löschen
|
||||
deleteBtn.addEventListener("click", () => {
|
||||
const name = docName.value.trim();
|
||||
|
||||
if (!name) {
|
||||
result.textContent = "Bitte Dokumentname angeben.";
|
||||
setTimeout(() => {
|
||||
result.textContent = "";
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmDelete = confirm(
|
||||
`Möchtest du das Dokument "${name}" wirklich löschen?`
|
||||
);
|
||||
|
||||
if (!confirmDelete) return;
|
||||
|
||||
window.api.deleteTxtFile(name).then((success) => {
|
||||
if (success) {
|
||||
result.textContent = "Dokument erfolgreich gelöscht!";
|
||||
reloadDocuments();
|
||||
existingDocs.value = "newDoc";
|
||||
existingDocs.dispatchEvent(new Event("change"));
|
||||
} else {
|
||||
result.textContent = "Dokument konnte nicht gelöscht werden.";
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
result.textContent = "";
|
||||
}, 3000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//function to load existingDoc options to the drop down list
|
||||
|
||||
window.api.getTxtFiles().then(files => {
|
||||
reloadDocuments();
|
||||
});
|
||||
|
||||
//content anzeigen
|
||||
existingDocs.addEventListener("change", async () => {
|
||||
const existingDocsed = existingDocs.value;
|
||||
const exampleText = "";
|
||||
|
||||
if (existingDocsed === "newDoc") {
|
||||
docNameWrapper.classList.remove("hidden");
|
||||
docName.value = "";
|
||||
prompt.value = exampleText;
|
||||
return;
|
||||
}
|
||||
docNameWrapper.classList.add("hidden");
|
||||
|
||||
const content = await window.api.readTxtFile(existingDocsed);
|
||||
prompt.value = content;
|
||||
docName.value = existingDocsed.replace(".txt", "");
|
||||
});
|
||||
|
||||
|
||||
+308
-160
@@ -1,103 +1,118 @@
|
||||
let currentVideoPath = null;
|
||||
//function to check if one checkbox is at least klicked
|
||||
function checkBoxes() {
|
||||
try {
|
||||
const checkboxes = document.querySelectorAll('input[name="docFormat"]');
|
||||
let isChecked = false;
|
||||
var checkedCounter = 0;
|
||||
checkboxes.forEach(function(checkbox){
|
||||
if(checkbox.checked){
|
||||
isChecked = true;
|
||||
checkedCounter++;
|
||||
}
|
||||
});
|
||||
|
||||
if (isChecked) {
|
||||
//Code to submit the video
|
||||
var selectedCheckboxes = {};
|
||||
checkboxes.forEach(function(checkbox){
|
||||
if(checkbox.checked){
|
||||
selectedCheckboxes[checkbox.nextElementSibling.textContent] = "";
|
||||
}
|
||||
});
|
||||
/*
|
||||
|
||||
const testEndings = [".mp4", ".mov", ".avi", ".mkv"];
|
||||
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
||||
var pathToLower = pathTest.toLowerCase();
|
||||
if(testEndings.some(e => pathToLower.endsWith(e))){
|
||||
//assembly of the json for the main
|
||||
Functions used in the setup or affect most of the gui
|
||||
|
||||
var typeCheckbox;
|
||||
if(document.getElementById("docFormat").checked) typeCheckbox = document.getElementById("docFormat").value;
|
||||
if(document.getElementById("docFormatSummary1").checked) typeCheckbox = document.getElementById("docFormatSummary1").value;
|
||||
if(document.getElementById("docFormatSummary2").checked) typeCheckbox = document.getElementById("docFormatSummary2").value;
|
||||
if(document.getElementById("docFormatSummary3").checked) typeCheckbox = document.getElementById("docFormatSummary3").value;
|
||||
if(document.getElementById("docFormatCustom").checked) typeCheckbox = document.getElementById("docFormatCustom").value;
|
||||
|
||||
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);
|
||||
const outputType = document.getElementById("output_type");
|
||||
const transcriptionType = document.getElementById("transkript_type");
|
||||
const aiType = document.getElementById("ai_type");
|
||||
const sendingPackage = {
|
||||
"video": {
|
||||
"module":"extraction-video-to-audio",
|
||||
"inputVideoPath": pathTest
|
||||
},
|
||||
"transcription": {
|
||||
"module": transcriptionType.value
|
||||
},
|
||||
"document": {
|
||||
"module":aiType.value,
|
||||
"type": typeCheckbox,
|
||||
"outputType": outputType.value
|
||||
}
|
||||
};
|
||||
window.submit.submit(sendingPackage)
|
||||
}else{
|
||||
alert('The given file is not compatible. These are the available types: [".mp4", ".mov", ".avi", ".mkv"].');
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//language only english at the moment
|
||||
alert('Please select at least one document type.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error in script.js checkBoxes function");
|
||||
console.log(error);
|
||||
*/
|
||||
var showCDValue = 0;
|
||||
function showCD() {
|
||||
if(showCDValue == 0){
|
||||
document.getElementById('cdContainer').style.display = "block";
|
||||
document.getElementById('step1').style.display ="none";
|
||||
document.getElementById('step2').style.display ="none";
|
||||
document.getElementById('step3').style.display ="none";
|
||||
document.getElementById('step4').style.display ="none";
|
||||
document.getElementById('step5').style.display ="none";
|
||||
document.getElementById('step6').style.display ="none";
|
||||
showCDValue = 1;
|
||||
} else {
|
||||
currentStep = 1;
|
||||
showCDValue = 0;
|
||||
document.getElementById('cdContainer').style.display = "none";
|
||||
showStep(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//language changing feature
|
||||
//language changing feature => changes the language of every displayed text
|
||||
function changeLanguage(language) {
|
||||
try {
|
||||
document.getElementById('labelLanguageFlag').src = languageOptions[language].flagPath;
|
||||
//document.getElementById('labelLanguageFlag').src = languageOptions[language].flagPath;
|
||||
document.getElementById('labelKI').textContent = languageOptions[language].labelKI;
|
||||
document.getElementById('labelTranscription').textContent = languageOptions[language].labelTranscription;
|
||||
document.getElementById('labelLanguage').textContent = languageOptions[language].labelLanguage;
|
||||
document.getElementById('title').textContent = languageOptions[language].title;
|
||||
document.getElementById('h1').textContent = languageOptions[language].h1;
|
||||
//document.getElementById('h1').textContent = languageOptions[language].h1;
|
||||
document.getElementById('p1').textContent = languageOptions[language].p1;
|
||||
document.getElementById('fileName').textContent = languageOptions[language].fileName;
|
||||
document.getElementById('manualUploadBtn').textContent = languageOptions[language].manualUploadBtn;
|
||||
document.getElementById('checkbox_group').textContent = languageOptions[language].checkbox_group;
|
||||
document.getElementById('label_format').textContent = languageOptions[language].label_format;
|
||||
document.getElementById('label_summary').textContent = languageOptions[language].label_summary;
|
||||
document.getElementById('submitButton').textContent = languageOptions[language].submitButton;
|
||||
document.getElementById('step_nav1').textContent = languageOptions[language].step_nav1;
|
||||
document.getElementById('step_nav2').textContent = languageOptions[language].step_nav2;
|
||||
document.getElementById('step_nav3').textContent = languageOptions[language].step_nav3;
|
||||
document.getElementById('step_nav4').textContent = languageOptions[language].step_nav4;
|
||||
document.getElementById('step_nav5').textContent = languageOptions[language].step_nav5;
|
||||
document.getElementById('step_nav6').textContent = languageOptions[language].step_nav6;
|
||||
//document.getElementById('h2').textContent = languageOptions[language].h2;
|
||||
document.getElementById('labelSpeaker').textContent = languageOptions[language].labelSpeaker;
|
||||
document.getElementById('labelSpeakerAudio').textContent = languageOptions[language].labelSpeakerAudio;
|
||||
document.getElementById('labelSpeakerWriter').textContent = languageOptions[language].labelSpeakerWriter;
|
||||
document.getElementById('speakerLocker').textContent = languageOptions[language].speakerLocker;
|
||||
document.getElementById('speakerResender').textContent = languageOptions[language].speakerResender;
|
||||
document.getElementById('downloadButton').textContent = languageOptions[language].downloadButton;
|
||||
document.getElementById('box1_p1').textContent = languageOptions[language].box1_p1;
|
||||
document.getElementById('box2_p2').textContent = languageOptions[language].box2_p2;
|
||||
document.getElementById('box3_p3').textContent = languageOptions[language].box3_p3;
|
||||
document.getElementById('labelType').textContent = languageOptions[language].labelType;
|
||||
|
||||
document.getElementById('customDocBtn').textContent = languageOptions[language].customDocBtn;
|
||||
document.getElementById('cd_h1').textContent = languageOptions[language].cd_h1;
|
||||
document.getElementById('cd_existingDocs').textContent = languageOptions[language].cd_existingDocs;
|
||||
document.getElementById('cd_docName').textContent = languageOptions[language].cd_docName;
|
||||
document.getElementById('docName').placeholder = languageOptions[language].docName;
|
||||
document.getElementById('cd_promt').textContent = languageOptions[language].cd_promt;
|
||||
document.getElementById('prompt').placeholder = languageOptions[language].prompt;
|
||||
document.getElementById('goBackBtn').textContent = languageOptions[language].goBackBtn;
|
||||
document.getElementById('deleteBtn').textContent = languageOptions[language].deleteBtn;
|
||||
document.getElementById('generateBtn').textContent = languageOptions[language].generateBtn;
|
||||
document.getElementById('newDoc').textContent = languageOptions[language].newDoc;
|
||||
|
||||
} catch (error) {
|
||||
console.log("Error in script.js changeLanguage function");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Functions used for the step navigation
|
||||
|
||||
*/
|
||||
|
||||
//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 = "flex";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Functions used in Step 1
|
||||
|
||||
*/
|
||||
|
||||
//function to display the file path in the drop down box
|
||||
function handleFiles(files) {
|
||||
try {
|
||||
@@ -119,27 +134,40 @@ function handleFiles(files) {
|
||||
|
||||
}
|
||||
|
||||
//function to regulate the progress on the progressbar
|
||||
function updateProgressBar(bar, value) {
|
||||
//Video thumbnail generation. Shows a scene from the selected video file as a preview
|
||||
function generateThumbnail(path) {
|
||||
try {
|
||||
value = Math.round(value);
|
||||
bar.querySelector(".progress_fill").style.width = `${value}%`;
|
||||
bar.querySelector(".progress_text").textContent = `${value}%`;
|
||||
const videoElement = document.getElementById("previewThumbnail");
|
||||
while (videoElement.firstChild) videoElement.removeChild(videoElement.firstChild);
|
||||
videoElement.src = path;
|
||||
videoElement.type = "video/mov";
|
||||
videoElement.load();
|
||||
videoElement.style.maxWidth = 40;
|
||||
videoElement.style.maxHeight = 40;
|
||||
videoElement.autoplay = false;
|
||||
} catch (error) {
|
||||
console.log("Error in scripts.js updateProgressBar function");
|
||||
console.log("Error in the generateThumbnail function in the script.js file \n");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Functions used in Step 2
|
||||
|
||||
*/
|
||||
|
||||
//function to load ai options to the drop down list
|
||||
function loadAiOptions(options){
|
||||
function loadAiOptions(options) {
|
||||
try {
|
||||
var menu = document.getElementById('ai_type');
|
||||
var object_holdy;
|
||||
var choice ;
|
||||
var choice;
|
||||
object_holdy = options
|
||||
for(i = 0; i < options.length; i++){
|
||||
for (i = 0; i < options.length; i++) {
|
||||
choice = document.createElement('option');
|
||||
choice.textContent = object_holdy[i].displayname;
|
||||
choice.value = object_holdy[i].name;
|
||||
@@ -152,13 +180,13 @@ function loadAiOptions(options){
|
||||
}
|
||||
|
||||
//function to load transcription options to the drop down list
|
||||
function loadTranscriptionOptions(options){
|
||||
function loadTranscriptionOptions(options) {
|
||||
try {
|
||||
var menu = document.getElementById('transkript_type');
|
||||
var object_holdy;
|
||||
var choice ;
|
||||
var choice;
|
||||
object_holdy = options
|
||||
for(i = 0; i < options.length; i++){
|
||||
for (i = 0; i < options.length; i++) {
|
||||
choice = document.createElement('option');
|
||||
choice.textContent = object_holdy[i].displayname;
|
||||
choice.value = object_holdy[i].name;
|
||||
@@ -171,13 +199,13 @@ function loadTranscriptionOptions(options){
|
||||
}
|
||||
|
||||
//function to load data type options to the drop down list
|
||||
function loadDataTypeOptions(options){
|
||||
function loadDataTypeOptions(options) {
|
||||
try {
|
||||
var menu = document.getElementById('output_type');
|
||||
var object_holdy;
|
||||
var choice ;
|
||||
var choice;
|
||||
object_holdy = options
|
||||
for(i = 0; i < options.length; i++){
|
||||
for (i = 0; i < options.length; i++) {
|
||||
choice = document.createElement('option');
|
||||
choice.textContent = object_holdy[i].displayname;
|
||||
choice.value = object_holdy[i].name;
|
||||
@@ -190,36 +218,177 @@ function loadDataTypeOptions(options){
|
||||
}
|
||||
|
||||
//function to load language options to the drop down list
|
||||
function loadLanguageOptions(){
|
||||
function loadLanguageOptions() {
|
||||
try {
|
||||
|
||||
var menu = document.getElementById('language_option');
|
||||
var menu_doc = document.getElementById('document_language_option');
|
||||
var object_holdy;
|
||||
var choice ;
|
||||
var choice;
|
||||
var choice2;
|
||||
object_holdy = Object.keys(languageOptions);
|
||||
for(i = 0; i < object_holdy.length; i++){
|
||||
for (i = 0; i < object_holdy.length; i++) {
|
||||
choice = document.createElement('option');
|
||||
choice.textContent = object_holdy[i];
|
||||
choice.value = object_holdy[i];
|
||||
choice.setAttribute('data-image', languageOptions[object_holdy[i]].flagPath);
|
||||
choice2 = document.createElement('option');
|
||||
choice2.textContent = object_holdy[i];
|
||||
choice2.value = object_holdy[i];
|
||||
choice2.setAttribute('data-image', languageOptions[object_holdy[i]].flagPath);
|
||||
menu_doc.appendChild(choice2);
|
||||
menu.appendChild(choice);
|
||||
|
||||
}
|
||||
new lc_select(document.getElementById('language_option')); //loads the flag images so they get displayed in the gui
|
||||
new lc_select(document.getElementById('document_language_option'));
|
||||
} catch (error) {
|
||||
console.log("Error in script.js loadLanguageOptions function");
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Functions used in Step 3
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Functions used in Step 4
|
||||
|
||||
*/
|
||||
|
||||
//function to check if one checkbox is at least klicked. Final controll function before sending the input to the generation
|
||||
function checkBoxes() {
|
||||
try {
|
||||
const checkboxes = document.querySelectorAll('input[name="docFormat"]');
|
||||
let isChecked = false;
|
||||
var checkedCounter = 0;
|
||||
checkboxes.forEach(function (checkbox) {
|
||||
if (checkbox.checked) {
|
||||
isChecked = true;
|
||||
checkedCounter++;
|
||||
}
|
||||
});
|
||||
|
||||
if (isChecked) {
|
||||
//Code to submit the video
|
||||
var selectedCheckboxes = {};
|
||||
checkboxes.forEach(function (checkbox) {
|
||||
if (checkbox.checked) {
|
||||
selectedCheckboxes[checkbox.nextElementSibling.textContent] = "";
|
||||
}
|
||||
});
|
||||
|
||||
const testEndings = [".mp4", ".mov", ".avi", ".mkv"];
|
||||
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
||||
var pathToLower = pathTest.toLowerCase();
|
||||
if (testEndings.some(e => pathToLower.endsWith(e))) {
|
||||
//assembly of the json for the main
|
||||
|
||||
var typeCheckbox;
|
||||
if (document.getElementById("docFormat").checked) typeCheckbox = document.getElementById("docFormat").value;
|
||||
if (document.getElementById("docFormatSummary1").checked) typeCheckbox = document.getElementById("docFormatSummary1").value;
|
||||
if (document.getElementById("docFormatSummary2").checked) typeCheckbox = document.getElementById("docFormatSummary2").value;
|
||||
if (document.getElementById("docFormatSummary3").checked) typeCheckbox = document.getElementById("docFormatSummary3").value;
|
||||
if (document.getElementById("docFormatCustom").checked) typeCheckbox = document.getElementById("docFormatCustom").value;
|
||||
|
||||
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);
|
||||
const outputType = document.getElementById("output_type");
|
||||
const transcriptionType = document.getElementById("transkript_type");
|
||||
const aiType = document.getElementById("ai_type");
|
||||
const sendingPackage = {
|
||||
"video": {
|
||||
"module": "extraction-video-to-audio",
|
||||
"inputVideoPath": pathTest
|
||||
},
|
||||
"transcription": {
|
||||
"module": transcriptionType.value
|
||||
},
|
||||
"document": {
|
||||
"module": aiType.value,
|
||||
"type": typeCheckbox,
|
||||
"outputType": outputType.value
|
||||
}
|
||||
};
|
||||
window.submit.submit(sendingPackage)
|
||||
} else {
|
||||
alert('The given file is not compatible. These are the available types: [".mp4", ".mov", ".avi", ".mkv"].');
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//language only english at the moment
|
||||
alert('Please select at least one document type.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error in script.js checkBoxes function");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//function the the submit button on step 4 can be pressed
|
||||
function activateSubmitBtn(hasFile) {
|
||||
try {
|
||||
document.getElementById("submitButton").disabled = !hasFile;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
//function to regulate the progress on the progressbar
|
||||
function updateProgressBar(bar, value) {
|
||||
try {
|
||||
value = Math.round(value);
|
||||
bar.querySelector(".progress_fill").style.width = `${value}%`;
|
||||
bar.querySelector(".progress_text").textContent = `${value}%`;
|
||||
} catch (error) {
|
||||
console.log("Error in scripts.js updateProgressBar function");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//function to hide the progressbar
|
||||
function deaktivateProgressbar() {
|
||||
try {
|
||||
document.getElementById("progressbar").style.visibility = "hidden";
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Functions used in Step 5
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//function to load speaker options to the drop down list
|
||||
function loadSpeakerOptions(options){
|
||||
function loadSpeakerOptions(options) {
|
||||
try {
|
||||
var menu = document.getElementById('cur_speaker');
|
||||
var l = document.getElementById('cur_speaker').options.length -1;
|
||||
for(i = l; i >= 0; i--){
|
||||
var l = document.getElementById('cur_speaker').options.length - 1;
|
||||
for (i = l; i >= 0; i--) {
|
||||
menu.remove(i);
|
||||
}
|
||||
var object_holdy;
|
||||
var choice;
|
||||
object_holdy = Object.keys(options);
|
||||
for(i = 0; i < object_holdy.length; i++){
|
||||
for (i = 0; i < object_holdy.length; i++) {
|
||||
choice = document.createElement('option');
|
||||
choice.textContent = options[object_holdy[i]].name;
|
||||
choice.value = object_holdy[i];
|
||||
@@ -233,7 +402,7 @@ function loadSpeakerOptions(options){
|
||||
}
|
||||
|
||||
//function to load speaker audio file options to the drop down list
|
||||
function loadSpeakerAudio(option){
|
||||
function loadSpeakerAudio(option) {
|
||||
try {
|
||||
var menu = document.getElementById('speakerAudioViewer');
|
||||
var aud = document.createElement("source");
|
||||
@@ -245,75 +414,20 @@ function loadSpeakerAudio(option){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function activateSubmitBtn(hasFile){
|
||||
try {
|
||||
document.getElementById("submitButton").disabled = !hasFile;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
function deaktivateProgressbar(){
|
||||
try {
|
||||
document.getElementById("progressbar").style.visibility = "hidden";
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
//Video thumbnail generation
|
||||
function generateThumbnail(path){
|
||||
const videoElement = document.getElementById("previewThumbnail");
|
||||
while (videoElement.firstChild) videoElement.removeChild(videoElement.firstChild);
|
||||
videoElement.src = path;
|
||||
videoElement.type = "video/mov";
|
||||
videoElement.load();
|
||||
videoElement.style.maxWidth = 40;
|
||||
videoElement.style.maxHeight = 40;
|
||||
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 = "flex";
|
||||
|
||||
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){
|
||||
function setSpeakerAudiosValue(valy) {
|
||||
try {
|
||||
speakerAudios = valy;
|
||||
speakerRewriten = valy;
|
||||
document.getElementById("speakerAudioViewer").src = valy.speakerA.src;
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteSpeakerName(){
|
||||
//Function to rewrite the speaker name in the json
|
||||
function rewriteSpeakerName() {
|
||||
try {
|
||||
var tempy = document.getElementById("cur_speaker").value;
|
||||
speakerAudios[tempy].name = document.getElementById("newSpeaker").value;
|
||||
@@ -322,15 +436,21 @@ function rewriteSpeakerName(){
|
||||
console.log("\n\n\n" + error + "\n\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
function sendSpeakerPackages(){
|
||||
//Function to send the json with the given names back to the program to rewrite the document file
|
||||
function sendSpeakerPackages() {
|
||||
try {
|
||||
window.submitSpeaker.speaker_submit(speakerAudios);
|
||||
} catch (error) {
|
||||
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Functions for Step 6
|
||||
|
||||
*/
|
||||
|
||||
function fileDownload() {
|
||||
try {
|
||||
window.download.file_download();
|
||||
@@ -338,3 +458,31 @@ function fileDownload() {
|
||||
console.error("Download failed:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Functions for the custom document section
|
||||
|
||||
*/
|
||||
|
||||
//reload drop down
|
||||
function reloadDocuments() {
|
||||
[...existingDocs.querySelectorAll('option:not([value="newDoc"])')]
|
||||
.forEach(o => o.remove());
|
||||
|
||||
window.api.getTxtFiles().then(files => {
|
||||
files.forEach(file => {
|
||||
const option = document.createElement('option');
|
||||
option.value = file;
|
||||
option.textContent = file
|
||||
.replace('.txt', '') // Endung entfernen
|
||||
.replace(/_/g, ' ') // Leerzeichen ersetzen
|
||||
.replace(/\b\w/g, c => c.toUpperCase()) // ersten Buchstaben groß
|
||||
existingDocs.appendChild(option);
|
||||
});
|
||||
});
|
||||
}
|
||||
+201
-111
@@ -9,7 +9,7 @@ body {
|
||||
gap: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
#h1 {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@@ -22,42 +22,42 @@ body {
|
||||
#h1-wrapper {
|
||||
position: relative;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
width: 770px;
|
||||
height: 60px;
|
||||
width: 780px;
|
||||
height: 60px;
|
||||
background-color: #FFF;
|
||||
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
width: 350px;
|
||||
height: 200px;
|
||||
transition: border 0.3s, background-color 0.3s;
|
||||
border: 2px dashed #7378c9;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.upload-container.dragover {
|
||||
border-color: #007BFF;
|
||||
background-color: #eaf0ff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.upload-container p {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: 16px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.file-name {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
@@ -66,19 +66,19 @@ body {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
#thumbnailContainer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
#thumbnailImage {
|
||||
width: 200px;
|
||||
height: auto;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ body {
|
||||
height: 100px;
|
||||
/*border: 1px dashed black;*/
|
||||
}
|
||||
|
||||
|
||||
.custom-btn {
|
||||
padding: 10px 20px;
|
||||
margin-top: 10px;
|
||||
@@ -98,81 +98,87 @@ body {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.custom-btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
|
||||
.submit-btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
#step2 {
|
||||
gap: 30px;
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
.KI-wrapper {
|
||||
margin-top: 40px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.checkbox-group {
|
||||
--borderColor: #007bfff5;
|
||||
--borderWidth: .125em;
|
||||
}
|
||||
--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-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-container{
|
||||
.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 {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
justify-items: left;
|
||||
@@ -186,7 +192,7 @@ input[type="file"] {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
margin: 130px auto 10px auto;
|
||||
margin: 110px auto 10px auto;
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
border: none;
|
||||
@@ -194,29 +200,29 @@ input[type="file"] {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
.submit-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
.mitte {
|
||||
background-color: #FFF;
|
||||
display: flex;
|
||||
width: 700px;
|
||||
width: 780px;
|
||||
height: 500px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40px;
|
||||
gap: 10px;
|
||||
border: 0px;
|
||||
border-color: black;
|
||||
border-style: solid;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 4px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.progressbar{
|
||||
|
||||
.progressbar {
|
||||
position: relative;
|
||||
width: 210px;
|
||||
height: 30px;
|
||||
@@ -226,15 +232,15 @@ input[type="file"] {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.progress_fill{
|
||||
|
||||
.progress_fill {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background: green;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.progress_text{
|
||||
|
||||
.progress_text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 5px;
|
||||
@@ -252,7 +258,9 @@ input[type="file"] {
|
||||
padding: 2px 10px 2px 10px;
|
||||
}
|
||||
|
||||
#ai_type, #transkript_type, #language_option {
|
||||
#ai_type,
|
||||
#transkript_type,
|
||||
#language_option {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@@ -260,7 +268,7 @@ input[type="file"] {
|
||||
gap: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow-wrap:inherit;
|
||||
overflow-wrap: inherit;
|
||||
padding-bottom: 20px;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 10px;
|
||||
@@ -274,7 +282,9 @@ input[type="file"] {
|
||||
background: #fff;
|
||||
padding: 10px 30px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
max-width: 720px;
|
||||
min-width: 720px;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
@@ -297,10 +307,11 @@ input[type="file"] {
|
||||
|
||||
/*panels*/
|
||||
.step {
|
||||
margin-top: 70px;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 400px;
|
||||
min-height: 425px;
|
||||
}
|
||||
|
||||
/*Navigation arrows*/
|
||||
@@ -336,7 +347,7 @@ input[type="file"] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.testy{
|
||||
.testy {
|
||||
background-color: #FFF;
|
||||
display: flex;
|
||||
width: auto;
|
||||
@@ -352,13 +363,13 @@ input[type="file"] {
|
||||
}
|
||||
|
||||
.box2 {
|
||||
background-color: red;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 5px;
|
||||
border: 1px solid black;
|
||||
margin: 5px;
|
||||
border-radius: 100px;
|
||||
background-color: red;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 5px;
|
||||
border: 1px solid black;
|
||||
margin: 5px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
li {
|
||||
@@ -394,24 +405,24 @@ li {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#toggle1:checked + .hamburger1 .top {
|
||||
#toggle1:checked+.hamburger1 .top {
|
||||
-webkit-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
margin-top: 22.5px;
|
||||
}
|
||||
|
||||
#toggle1:checked + .hamburger1 .meat {
|
||||
#toggle1:checked+.hamburger1 .meat {
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
#toggle1:checked + .hamburger1 .bottom {
|
||||
#toggle1:checked+.hamburger1 .bottom {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
#toggle1:checked ~ .menu1 {
|
||||
#toggle1:checked~.menu1 {
|
||||
height: 150px;
|
||||
width: 300px;
|
||||
}
|
||||
@@ -465,7 +476,9 @@ li {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#step2, #step3, #step5 {
|
||||
#step2,
|
||||
#step3,
|
||||
#step5 {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
@@ -489,10 +502,7 @@ li {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
margin-left: auto;
|
||||
margin-right: 0px;
|
||||
margin-top: 130px;
|
||||
margin-bottom: 10px;
|
||||
margin: 110px auto 10px auto;
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
border: none;
|
||||
@@ -501,7 +511,8 @@ li {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#speakerLocker, #speakerResender{
|
||||
#speakerLocker,
|
||||
#speakerResender {
|
||||
padding: 10px 20px;
|
||||
margin: 20px auto;
|
||||
background-color: #007BFF;
|
||||
@@ -510,4 +521,83 @@ li {
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.h2 {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.speakerView,
|
||||
.speakerAudio,
|
||||
.speakerWrite {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.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: 650px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
textarea,
|
||||
select {
|
||||
width: 80%;
|
||||
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;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,89 +1,110 @@
|
||||
// Loading required packages
|
||||
require("./requires.js")
|
||||
require("./requires.js");
|
||||
console.log(start);
|
||||
|
||||
|
||||
// Initialising map to be used to store the functionality later on for reloadability
|
||||
mapFunctions = new Map()
|
||||
const https = require("https");
|
||||
let un = process.env.auth_username
|
||||
let pw = process.env.auth_password
|
||||
|
||||
|
||||
// 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);
|
||||
const options = {
|
||||
hostname: "keyserver.dommymommy.xyz",
|
||||
port: 443,
|
||||
path: "/v1/auth",
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"username": un,
|
||||
"password": pw
|
||||
}
|
||||
};
|
||||
|
||||
const req = https.request(options, (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
res.setEncoding("utf8");
|
||||
let data = "";
|
||||
res.on("data", (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on("end", () => {
|
||||
const myJson = JSON.parse(data);
|
||||
Object.keys(myJson).forEach(el => {
|
||||
// console.log(el, myJson[el]);
|
||||
process.env[el] = myJson[el]
|
||||
})
|
||||
});
|
||||
} else if (res.statusCode === 401) {
|
||||
res.setEncoding("utf8");
|
||||
let data = "";
|
||||
res.on("data", (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on("end", () => {
|
||||
console.log(data);
|
||||
process.exit()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
req.on("error", (error) => {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
// The startup information for the project, here you can add stuff that might be nice to see when the app starts
|
||||
mapFunctions.get("Startup_function").function()
|
||||
console.log("------------------------------------ Status ------------------------------------");
|
||||
console.log(__dirname);
|
||||
console.log(platform);
|
||||
console.log(`The Startup took ${new Date() - start}ms`)
|
||||
console.log(`${mapFunctions.size} Function modules loaded`);
|
||||
console.log("--------------------------------------------------------------------------------");
|
||||
req.end();
|
||||
|
||||
|
||||
|
||||
// Initialising map to be used to store the functionality later on for reloadability
|
||||
mapFunctions = new Map();
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------- CLI COMMANDS --------------------------------------------------------- //
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
rl.on("line", data =>{
|
||||
const args = data.trim().split(" ");
|
||||
const command = args.shift().toLowerCase();
|
||||
mapFunctions.get("cliCommands").function(command, args)
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
// The startup information for the project, here you can add stuff that might be nice to see when the app starts
|
||||
mapFunctions.get("Startup_function").function();
|
||||
console.log(
|
||||
"------------------------------------ Status ------------------------------------"
|
||||
);
|
||||
console.log(__dirname);
|
||||
console.log(platform);
|
||||
console.log(`The Startup took ${new Date() - start}ms`);
|
||||
console.log(`${mapFunctions.size} Function modules loaded`);
|
||||
console.log("--------------------------------------------------------------------------------");
|
||||
|
||||
// ----------------------------------------------------------- ELECTRON ----------------------------------------------------------- //
|
||||
|
||||
let mainWindow;
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: `${mainDir}/electron/main/preload.js`
|
||||
}
|
||||
});
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: `${mainDir}/electron/main/preload.js`,
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.loadFile('./electron/main/index.html');
|
||||
mainWindow.loadFile("./electron/main/index.html");
|
||||
}
|
||||
|
||||
electron.app.whenReady().then(createWindow);
|
||||
|
||||
|
||||
// electron.ipcMain.on("extract", (event, args) => {
|
||||
// mapFunctions.get("extraction-video-to-audio").function(args)
|
||||
// })
|
||||
|
||||
// setTimeout(() => {
|
||||
// mainWindow.webContents.send("fuck", "worked uwu")
|
||||
// }, 5000);
|
||||
|
||||
electron.ipcMain.handle('get-module-names', async () => {
|
||||
let module_array = {
|
||||
"ai_modules":[],
|
||||
@@ -103,7 +124,6 @@ electron.ipcMain.handle('get-module-names', async () => {
|
||||
return module_array
|
||||
});
|
||||
|
||||
|
||||
// electron.ipcMain.on("get_modules", async (event, args) => {
|
||||
// let module_array = {
|
||||
// "ai_modules":[],
|
||||
@@ -124,160 +144,206 @@ electron.ipcMain.handle('get-module-names', async () => {
|
||||
// mainWindow.webContents.send("modules", module_array)
|
||||
// })
|
||||
|
||||
var globalArgs = {}
|
||||
var globalFinalHtmlPath = ""
|
||||
var globalArgs = {};
|
||||
var globalFinalHtmlPath = "";
|
||||
|
||||
electron.ipcMain.on("file_submit", async (event, args) => {
|
||||
try {
|
||||
globalArgs = args
|
||||
let curstep = 0
|
||||
let totalsteps = 4
|
||||
try {
|
||||
globalArgs = args;
|
||||
let curstep = 0;
|
||||
let totalsteps = 4;
|
||||
|
||||
const TEMPLATE_MAP = {
|
||||
"followup-report": "followup_report.txt",
|
||||
"agenda": "agenda.txt",
|
||||
"result-protocol": "result_protocol.txt",
|
||||
"sprint-planning": "sprint_planning_note.txt",
|
||||
"custom": "custom_document.txt"
|
||||
};
|
||||
const TEMPLATE_MAP = {
|
||||
"followup-report": "followup_report.txt",
|
||||
agenda: "agenda.txt",
|
||||
"result-protocol": "result_protocol.txt",
|
||||
"sprint-planning": "sprint_planning_note.txt",
|
||||
custom: "custom_document.txt",
|
||||
};
|
||||
|
||||
const templateFile = TEMPLATE_MAP[args.document.type];
|
||||
const templateFile = TEMPLATE_MAP[args.document.type];
|
||||
|
||||
if (!templateFile) {
|
||||
throw new Error("Unknown document type: " + args.document.type);
|
||||
}
|
||||
|
||||
console.log(args);
|
||||
let audiopath = ""
|
||||
let transcriptpath = ""
|
||||
|
||||
console.log("\n\n Running the Video to Audio Extractor");
|
||||
// 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 => {
|
||||
console.log(resp);
|
||||
audiopath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
console.log("\n\n Running the Audio to Transcription module");
|
||||
// TODO implement transcription module
|
||||
// This code handles the Audio to Text transcription module call
|
||||
await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
console.log("\n\n Running the Transcription Summarizer module");
|
||||
// This code summarises the transcript, so that it can be used by an llm
|
||||
// await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => {
|
||||
await mapFunctions.get("summarize-transcription2").function(transcriptpath).then(resp => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
console.log("\n\n Running the LLM module");
|
||||
// TODO implement documentation module
|
||||
// This code handles the Text to Document processing module call
|
||||
|
||||
console.log(`\n\n Running the LLM for Document Style ${args.document.type}`);
|
||||
|
||||
await mapFunctions.get("module-handler").function(args.document.module, { inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/" + templateFile, language: "en" }).then(resp => {
|
||||
console.log(resp);
|
||||
globalFinalHtmlPath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
await mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: transcriptpath }).then(resp => {
|
||||
mainWindow.webContents.send("speakerAudios", resp)
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (!templateFile) {
|
||||
throw new Error("Unknown document type: " + args.document.type);
|
||||
}
|
||||
})
|
||||
|
||||
electron.ipcMain.on("file_download", async() => {
|
||||
await mapFunctions.get("htmlDocumentConverter").convert({inputPath:globalFinalHtmlPath, format: globalArgs.document.outputType, showDialog: true});
|
||||
})
|
||||
console.log(args);
|
||||
let audiopath = "";
|
||||
let transcriptpath = "";
|
||||
|
||||
electron.ipcMain.on("speaker_submit", async() => {
|
||||
console.log("\n\n\nJa also hier kam was an \n\n\n");
|
||||
})
|
||||
|
||||
let q =
|
||||
{
|
||||
video: {
|
||||
module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio
|
||||
inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like
|
||||
outputType: "String" // The file format to be used for the audio output file, such as wav, mp3, flac and so on
|
||||
},
|
||||
transcription:{
|
||||
module: "String" // The module name of the transcription model you want to use
|
||||
},
|
||||
document:{
|
||||
module: "String", // The module name of the AI model you want to use to create the document
|
||||
styles: [ // An array of all the document styles/prompts you want to have the document be processed with
|
||||
{
|
||||
prompt: "String",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
console.log("\n\n Running the Video to Audio Extractor");
|
||||
// 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) => {
|
||||
console.log(resp);
|
||||
audiopath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
let q1 = {
|
||||
"ai_modules": [
|
||||
{name:"abc", displayname:"ABC"},
|
||||
{name:"qeg", displayname:"aqghegahu"}
|
||||
console.log("\n\n Running the Audio to Transcription module");
|
||||
// TODO implement transcription module
|
||||
// This code handles the Audio to Text transcription module call
|
||||
await mapFunctions
|
||||
.get("module-handler")
|
||||
.function(args.transcription.module, audiopath)
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
|
||||
console.log("\n\n Running the Transcription Summarizer module");
|
||||
// This code summarises the transcript, so that it can be used by an llm
|
||||
// await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => {
|
||||
await mapFunctions
|
||||
.get("summarize-transcription2")
|
||||
.function(transcriptpath)
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
console.log("\n\n Running the LLM module");
|
||||
// TODO implement documentation module
|
||||
// This code handles the Text to Document processing module call
|
||||
|
||||
console.log(
|
||||
`\n\n Running the LLM for Document Style ${args.document.type}`
|
||||
);
|
||||
|
||||
await mapFunctions
|
||||
.get("module-handler")
|
||||
.function(args.document.module, {
|
||||
inputTranscriptPath: transcriptpath,
|
||||
documentTypePath: "./storage/documentType/" + templateFile,
|
||||
language: "en",
|
||||
})
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
globalFinalHtmlPath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
await mapFunctions
|
||||
.get("extract-speaker-snippets")
|
||||
.function({ audioPath: audiopath, jsonPath: transcriptpath })
|
||||
.then((resp) => {
|
||||
mainWindow.webContents.send("speakerAudios", resp);
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("file_download", async () => {
|
||||
await mapFunctions
|
||||
.get("htmlDocumentConverter")
|
||||
.convert({
|
||||
inputPath: globalFinalHtmlPath,
|
||||
format: globalArgs.document.outputType,
|
||||
showDialog: true,
|
||||
});
|
||||
});
|
||||
|
||||
electron.ipcMain.on("speaker_submit", async (event, args) => {
|
||||
console.log("\n\n\nJa also hier kam was an \n\n\n");
|
||||
console.log(args);
|
||||
|
||||
try {
|
||||
await mapFunctions.get("replace_speaker").function(args);
|
||||
event.reply("speaker_submit_response", { success: true });
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
event.reply("speaker_submit_response", {
|
||||
success: false,
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let q = {
|
||||
video: {
|
||||
module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio
|
||||
inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like
|
||||
outputType: "String", // The file format to be used for the audio output file, such as wav, mp3, flac and so on
|
||||
},
|
||||
transcription: {
|
||||
module: "String", // The module name of the transcription model you want to use
|
||||
},
|
||||
document: {
|
||||
module: "String", // The module name of the AI model you want to use to create the document
|
||||
styles: [
|
||||
// An array of all the document styles/prompts you want to have the document be processed with
|
||||
{
|
||||
prompt: "String",
|
||||
},
|
||||
],
|
||||
"transcription_modules": [
|
||||
{name:"abc", displayname:"ABC"},
|
||||
{name:"qeg", displayname:"aqghegahu"}
|
||||
]
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
//gibt Documentfiles an preload zurück
|
||||
|
||||
electron.ipcMain.handle('get-txt-files', () => {
|
||||
const storagePath = `${mainDir}/storage/documentType`
|
||||
electron.ipcMain.handle("get-txt-files", () => {
|
||||
const storagePath = `${mainDir}/storage/documentType`;
|
||||
|
||||
return fs.readdirSync(storagePath)
|
||||
.filter(f => f.endsWith('.txt'))
|
||||
return fs.readdirSync(storagePath).filter((f) => f.endsWith(".txt"));
|
||||
});
|
||||
|
||||
//speichern neuer document types
|
||||
|
||||
electron.ipcMain.handle('save-txt-file', (event, fileName, content) => {
|
||||
electron.ipcMain.handle("save-txt-file", (event, fileName, content) => {
|
||||
const filePath = `${mainDir}/storage/documentType/${fileName}.txt`;
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -298,4 +364,4 @@ electron.ipcMain.handle('delete-txt-file', (event, fileName) => {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -22,4 +22,4 @@ electron = require('electron');
|
||||
|
||||
axios = require("axios")
|
||||
|
||||
console.log(require('dotenv').config({path: __dirname + '/.env'}));
|
||||
require('dotenv').config({path: __dirname + '/.env'});
|
||||
@@ -8,7 +8,7 @@ if (!fs.existsSync(outputDir)) {
|
||||
}
|
||||
|
||||
// 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
|
||||
let 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 = {
|
||||
@@ -18,6 +18,7 @@ const module_exports = {
|
||||
description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform",
|
||||
|
||||
async function(parameter) {
|
||||
SAIA_API_KEY = process.env.SAIA_API_KEY;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// console.log("SAIA OpenAI GPT module invoked with parameters:", parameter);
|
||||
|
||||
@@ -8,7 +8,7 @@ if (!fs.existsSync(outputDir)) {
|
||||
}
|
||||
|
||||
// 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"
|
||||
let GEMINI_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 = {
|
||||
@@ -18,6 +18,7 @@ const module_exports = {
|
||||
description: "Generates documents using Google Gemini LLM",
|
||||
|
||||
async function(parameter) {
|
||||
GEMINI_API_KEY = process.env.GOOGLE_API_KEY;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// console.log("Gemini LLM module invoked with parameters:", parameter);
|
||||
|
||||
@@ -8,7 +8,7 @@ if (!fs.existsSync(outputDir)) {
|
||||
}
|
||||
|
||||
// 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;
|
||||
let 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 = {
|
||||
@@ -18,6 +18,7 @@ const module_exports = {
|
||||
description: "Generates documents using QWEN 3 235B via SAIA platform",
|
||||
|
||||
async function(parameter) {
|
||||
SAIA_API_KEY = process.env.SAIA_API_KEY;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const module_exports = {
|
||||
name: "replace_speaker",
|
||||
type: "processor",
|
||||
displayname: "Speaker Name Replacer",
|
||||
description: "Replaces speaker placeholder names with actual names based on a mapping in HTML files",
|
||||
|
||||
async function(speakerMapping) {
|
||||
// Relativ von dieser Datei aus
|
||||
const documentsDir = path.resolve(__dirname, '../../../storage/documents');
|
||||
const inputHtmlPath = await this.getNewestFile(documentsDir, '.html');
|
||||
|
||||
if (!inputHtmlPath) {
|
||||
throw new Error(`No HTML files found in ${documentsDir}`);
|
||||
}
|
||||
|
||||
return await this.replaceNames(inputHtmlPath, speakerMapping);
|
||||
},
|
||||
|
||||
getNewestFile: async function(dirPath, extension) {
|
||||
try {
|
||||
const files = await fs.promises.readdir(dirPath);
|
||||
const filtered = files.filter(f => f.endsWith(extension));
|
||||
|
||||
if (filtered.length === 0) return null;
|
||||
|
||||
const filesWithStats = await Promise.all(
|
||||
filtered.map(async (f) => {
|
||||
const fullPath = path.join(dirPath, f);
|
||||
const stats = await fs.promises.stat(fullPath);
|
||||
return { path: fullPath, time: stats.mtimeMs };
|
||||
})
|
||||
);
|
||||
|
||||
return filesWithStats.reduce((newest, curr) =>
|
||||
curr.time > newest.time ? curr : newest
|
||||
).path;
|
||||
} catch (error) {
|
||||
console.error("Error reading directory:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
replaceNames: async function(inputHtmlPath, speakerMapping) {
|
||||
try {
|
||||
const htmlContent = await fs.promises.readFile(inputHtmlPath, "utf-8");
|
||||
|
||||
let outputContent = htmlContent;
|
||||
Object.entries(speakerMapping).forEach(([placeholder, value]) => {
|
||||
// Extract name if value is an object
|
||||
const displayName = typeof value === 'string' ? value : value.name;
|
||||
|
||||
// Normalize placeholder for matching (remove case sensitivity)
|
||||
const normalizedPlaceholder = placeholder.toLowerCase();
|
||||
|
||||
// Replace all variations: speakerA, SpeakerA, SPEAKERA, speaker_a, Speaker A, etc.
|
||||
// Matches with optional spaces, underscores, and parentheses
|
||||
const regex = new RegExp(
|
||||
`\\b[Ss]peaker\\s*[_-]?\\s*${placeholder.charAt(placeholder.length - 1)}\\b|\\b${placeholder}\\b`,
|
||||
'gi'
|
||||
);
|
||||
|
||||
outputContent = outputContent.replace(regex, displayName);
|
||||
});
|
||||
|
||||
await fs.promises.writeFile(inputHtmlPath, outputContent, "utf-8");
|
||||
|
||||
return inputHtmlPath;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error replacing speaker names:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = module_exports;
|
||||
@@ -0,0 +1,54 @@
|
||||
// -----------------------------------------------------------
|
||||
// Parakeet (Step 3A: spawn Python minimal integration)
|
||||
// -----------------------------------------------------------
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { spawn } = require("child_process");
|
||||
|
||||
module.exports = {
|
||||
name: "parakeet",
|
||||
type: "transcription",
|
||||
displayname: "NVIDIA Parakeet",
|
||||
|
||||
async function(audioFilePath) {
|
||||
console.log("🦜 [Parakeet] Starting test integration (spawn only)...");
|
||||
console.log("🦜 Input audio:", audioFilePath);
|
||||
|
||||
// Check audio exists
|
||||
if (!fs.existsSync(audioFilePath)) {
|
||||
throw new Error("Audio file does not exist: " + audioFilePath);
|
||||
}
|
||||
|
||||
// Output path in storage/transcripts
|
||||
const sessionId = path.basename(audioFilePath).replace(/\.[^.]+$/, "");
|
||||
const outputDir = path.join(__dirname, "../../../storage/transcripts");
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
|
||||
const outputPath = path.join(outputDir, `${sessionId}.json`);
|
||||
|
||||
// -------------------------------------------------------
|
||||
// SPAWN PYTHON SCRIPT (step 3A — dummy script)
|
||||
// -------------------------------------------------------
|
||||
return new Promise((resolve, reject) => {
|
||||
const python310 = "C:\\Users\\smith\\AppData\\Local\\Programs\\Python\\Python310\\python.exe";
|
||||
const py = spawn(python310, [
|
||||
path.join(__dirname, "parakeet_transcribe.py"),
|
||||
audioFilePath,
|
||||
outputPath
|
||||
]);
|
||||
|
||||
py.stdout.on("data", data => console.log("🦜 [Python]", data.toString().trim()));
|
||||
py.stderr.on("data", data => console.error("🦜 [Python ERR]", data.toString().trim()));
|
||||
|
||||
py.on("close", code => {
|
||||
if (code === 0) {
|
||||
console.log("🦜 [Parakeet] Done (spawn test). Output:", outputPath);
|
||||
resolve(outputPath);
|
||||
} else {
|
||||
reject(new Error("Python script failed with exit code " + code));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
# -----------------------------------------------------------
|
||||
# Parakeet Real Transcriber (NVIDIA NeMo + PyTorch GPU)
|
||||
# -----------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import json
|
||||
import soundfile as sf
|
||||
import torch
|
||||
from nemo.collections.asr.models import ASRModel
|
||||
|
||||
# Args:
|
||||
# sys.argv[1] = input audio path
|
||||
# sys.argv[2] = output JSON path
|
||||
|
||||
audio_path = sys.argv[1]
|
||||
output_path = sys.argv[2]
|
||||
|
||||
print("🔥 Starting Parakeet model...")
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
print("🔥 Using device:", device)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Load Parakeet model (NVIDIA pretrained ASR)
|
||||
# -----------------------------------------------------------
|
||||
model = ASRModel.from_pretrained(model_name="nvidia/parakeet-ctc-0.6b")
|
||||
model = model.to(device)
|
||||
model.eval()
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Load audio
|
||||
# -----------------------------------------------------------
|
||||
print("🎧 Loading audio:", audio_path)
|
||||
audio, sr = sf.read(audio_path)
|
||||
|
||||
# model expects mono float32
|
||||
if len(audio.shape) > 1:
|
||||
audio = audio.mean(axis=1)
|
||||
|
||||
audio = audio.astype("float32")
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Run inference
|
||||
# -----------------------------------------------------------
|
||||
print("🧠 Running inference...")
|
||||
with torch.no_grad():
|
||||
hyp = model.transcribe([audio])[0]
|
||||
|
||||
# Extract only the text
|
||||
if hasattr(hyp, "text"):
|
||||
transcript = hyp.text
|
||||
else:
|
||||
# fallback: convert to string (rare)
|
||||
transcript = str(hyp)
|
||||
|
||||
print("📄 Transcript:", transcript)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Save JSON format compatible with V2D pipeline
|
||||
# -----------------------------------------------------------
|
||||
result = {
|
||||
"id": output_path.split("/")[-1].replace(".json", ""),
|
||||
"tool": "nemo_parakeet",
|
||||
"status": "completed",
|
||||
"text": transcript,
|
||||
"words": [] # Parakeet XS doesn’t return word timestamps
|
||||
}
|
||||
|
||||
with open(output_path, "w", encoding="utf-8") as f:
|
||||
json.dump(result, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print("✔ JSON saved at:", output_path)
|
||||
@@ -1,4 +1,4 @@
|
||||
const API_KEY = process.env.ASSEMBLYAI_API_KEY;
|
||||
let API_KEY
|
||||
const BASE_URL = 'https://api.assemblyai.com/v2';
|
||||
|
||||
//---------------------------------------------------Upload audio---------------------------------------------------
|
||||
@@ -92,6 +92,7 @@ module.exports = {
|
||||
audioformat: "mp3",
|
||||
|
||||
async function(audioFileName) {
|
||||
API_KEY = process.env.ASSEMBLYAI_API_KEY;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// audioFileName ist nur "datei.mp3"
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
# Meeting Agenda Generator
|
||||
|
||||
Du bist ein erfahrener Moderator und Projektmanager.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem folgenden Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
ANFORDERUNGEN:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem Meeting-Transkript.
|
||||
|
||||
## ANFORDERUNGEN:
|
||||
- Rekonstruiere die tatsächlichen Themenblöcke
|
||||
- Ordne sie logisch und chronologisch
|
||||
- Fasse ähnliche Diskussionen zusammen
|
||||
- Keine irrelevanten Details aufnehmen
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
- Titel der Agenda
|
||||
- Ziel des Meetings (1–2 Sätze)
|
||||
- Agenda-Punkte (nummeriert)
|
||||
- Thema
|
||||
- Kurzbeschreibung
|
||||
- Ziel des Punktes (Information, Entscheidung, Diskussion)
|
||||
## STRUKTUR:
|
||||
|
||||
STIL:
|
||||
### 1. Titel der Agenda
|
||||
|
||||
### 2. Ziel des Meetings
|
||||
- 1–2 präzise Sätze
|
||||
|
||||
### 3. Agenda-Punkte (nummeriert)
|
||||
Für jeden Punkt:
|
||||
- **Thema**
|
||||
- **Kurzbeschreibung**
|
||||
- **Ziel des Punktes:** (Information / Entscheidung / Diskussion)
|
||||
|
||||
## STIL:
|
||||
- Klar, kompakt
|
||||
- Business-orientiert
|
||||
- Keine Sprecher- oder Zeitangaben
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Logische Reihenfolge
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,22 +1,44 @@
|
||||
# Custom Document Generator
|
||||
|
||||
Du bist ein intelligenter Dokumenten-Generator.
|
||||
|
||||
AUFGABE:
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle ein individuelles Dokument basierend auf:
|
||||
1) dem Meeting-Transkript
|
||||
2) der zusätzlichen Nutzeranweisung
|
||||
1. dem Meeting-Transkript
|
||||
2. der zusätzlichen Nutzeranweisung
|
||||
|
||||
WICHTIG:
|
||||
- Priorisiere die Nutzeranweisung
|
||||
## ANFORDERUNGEN:
|
||||
- **Priorisiere die Nutzeranweisung** über standardisierte Strukturen
|
||||
- Nutze das Transkript als Wissensquelle
|
||||
- Struktur, Tonalität und Detailgrad anpassen
|
||||
- Struktur, Tonalität und Detailgrad nach Nutzervorgabe anpassen
|
||||
- Inhalte logisch zusammenführen
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
FORMAT:
|
||||
- Passe Struktur und Stil an den Nutzerwunsch an
|
||||
- Klare Überschriften
|
||||
- Keine Sprecher- oder Zeitangaben
|
||||
## VORGEHEN:
|
||||
1. Lese die Nutzeranweisung sorgfältig
|
||||
2. Extrahiere aus dem Transkript die relevanten Informationen
|
||||
3. Erstelle das Dokument nach der gewünschten Struktur
|
||||
4. Behalte Sprecher-Platzhalter unverändert
|
||||
|
||||
TRANSKRIPT & NUTZERANWEISUNG:
|
||||
## ALLGEMEINE RICHTLINIEN:
|
||||
- Entferne Redundanzen und Smalltalk
|
||||
- Keine Zeitstempel oder Sprecherangaben (wenn nicht gefordert)
|
||||
- Sachlich, präzise, professionell
|
||||
- Keine Spekulationen oder Meinungen (wenn nicht gefordert)
|
||||
|
||||
---
|
||||
|
||||
**NUTZERANWEISUNG:**
|
||||
[Hier kommt die Anforderung des Nutzers hin]
|
||||
|
||||
**TRANSKRIPT:**
|
||||
[Hier kommt das Meeting-Transkript hin]
|
||||
@@ -1,45 +1,61 @@
|
||||
# Follow-up Report Generator
|
||||
|
||||
Du bist ein professioneller Meeting-Analyst und Business Writer.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle einen strukturierten Follow-up Report basierend auf dem folgenden Meeting-Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
ANFORDERUNGEN:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle einen strukturierten Follow-up Report basierend auf dem Meeting-Transkript.
|
||||
|
||||
## ANFORDERUNGEN:
|
||||
- Fasse Inhalte sinngemäß zusammen
|
||||
- Entferne Redundanzen und Smalltalk
|
||||
- Formuliere klar, präzise und professionell
|
||||
- Verwende neutrale Business-Sprache
|
||||
- Keine Zeitstempel oder Sprecher-Namen zitieren
|
||||
- Leite Entscheidungen und Aufgaben logisch ab, wenn sie implizit sind
|
||||
- Markiere offene Punkte klar
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR DES DOKUMENTS:
|
||||
1. Titel & Metadaten
|
||||
- Meetingtitel (ableiten)
|
||||
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben“)
|
||||
- Teilnehmer (zusammengefasst)
|
||||
## STRUKTUR DES DOKUMENTS:
|
||||
|
||||
2. Executive Summary (max. 5 Bullet Points)
|
||||
### 1. Titel & Metadaten
|
||||
- Meetingtitel (ableiten)
|
||||
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben")
|
||||
- Teilnehmer (zusammengefasst)
|
||||
|
||||
3. Besprochene Themen
|
||||
- Thema
|
||||
- Kernaussagen
|
||||
- Relevante Erkenntnisse
|
||||
### 2. Executive Summary
|
||||
- Max. 5 Bullet Points
|
||||
- Kernpunkte zusammenfassen
|
||||
|
||||
4. Entscheidungen
|
||||
- Entscheidung
|
||||
- Kontext / Begründung
|
||||
### 3. Besprochene Themen
|
||||
- Thema
|
||||
- Kernaussagen
|
||||
- Relevante Erkenntnisse
|
||||
|
||||
5. Action Items
|
||||
- Aufgabe
|
||||
- Verantwortlich (falls ableitbar)
|
||||
- Ziel / Zweck
|
||||
### 4. Entscheidungen
|
||||
- Entscheidung
|
||||
- Kontext / Begründung
|
||||
|
||||
6. Offene Fragen & Risiken
|
||||
### 5. Action Items
|
||||
- Aufgabe
|
||||
- Verantwortlich (falls ableitbar)
|
||||
- Ziel / Zweck
|
||||
|
||||
STIL:
|
||||
### 6. Offene Fragen & Risiken
|
||||
|
||||
## STIL:
|
||||
- Überschriften klar strukturiert
|
||||
- Bullet Points bevorzugen
|
||||
- Präzise, keine Umgangssprache
|
||||
- Keine Zeitstempel oder Sprecherangaben
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,27 +1,54 @@
|
||||
# Result Protocol Generator
|
||||
|
||||
Du bist ein professioneller Protokollführer.
|
||||
|
||||
AUFGABE:
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle ein Ergebnisprotokoll basierend auf dem Meeting-Transkript.
|
||||
|
||||
FOKUS:
|
||||
## FOKUS:
|
||||
- Ergebnisse statt Diskussionen
|
||||
- Entscheidungen, Beschlüsse, Vereinbarungen
|
||||
- Klare, überprüfbare Aussagen
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
1. Meeting-Informationen
|
||||
2. Ergebnisse je Thema
|
||||
- Thema
|
||||
- Ergebnis / Beschluss
|
||||
3. Entscheidungen
|
||||
4. Aufgaben & Verantwortlichkeiten
|
||||
5. Offene Punkte
|
||||
## STRUKTUR:
|
||||
|
||||
REGELN:
|
||||
### 1. Meeting-Informationen
|
||||
- Titel
|
||||
- Datum
|
||||
- Teilnehmer
|
||||
|
||||
### 2. Ergebnisse je Thema
|
||||
- **Thema**
|
||||
- **Ergebnis / Beschluss**
|
||||
|
||||
### 3. Entscheidungen
|
||||
- Klare Entscheidungen mit Kontext
|
||||
|
||||
### 4. Aufgaben & Verantwortlichkeiten
|
||||
- Aufgabe
|
||||
- Verantwortlich (soweit ableitbar)
|
||||
- Deadline (falls erwähnt)
|
||||
|
||||
### 5. Offene Punkte
|
||||
- Ungelöste Fragen
|
||||
- Ausstehende Klärungen
|
||||
|
||||
## REGELN:
|
||||
- Keine Meinungen oder Spekulationen
|
||||
- Keine Zeit- oder Sprecherangaben
|
||||
- Sachlich, formal
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Fokus auf Fakten und Ergebnisse
|
||||
|
||||
---
|
||||
|
||||
TRANSKRIPT:
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,35 +1,61 @@
|
||||
# Sprint Planning Note Generator
|
||||
|
||||
Du bist ein erfahrener Scrum Master.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle Sprint Planning Notes aus dem folgenden Meeting-Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
FOKUS:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle Sprint Planning Notes aus dem Meeting-Transkript.
|
||||
|
||||
## FOKUS:
|
||||
- Sprint-Ziele
|
||||
- User Stories / Tasks
|
||||
- Abhängigkeiten
|
||||
- Risiken
|
||||
- Commitments
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
1. Sprint Overview
|
||||
- Sprint-Ziel
|
||||
- Zeitraum (falls erwähnt)
|
||||
## STRUKTUR:
|
||||
|
||||
2. Geplante Arbeit
|
||||
- User Story / Task
|
||||
- Beschreibung
|
||||
- Akzeptanzkriterien (falls ableitbar)
|
||||
### 1. Sprint Overview
|
||||
- **Sprint-Ziel:** (Kurz und prägnant)
|
||||
- **Zeitraum:** (Falls im Transkript erwähnt)
|
||||
|
||||
3. Abhängigkeiten & Blocker
|
||||
### 2. Geplante Arbeit
|
||||
Für jede User Story / Task:
|
||||
- **Titel**
|
||||
- **Beschreibung**
|
||||
- **Akzeptanzkriterien** (falls ableitbar)
|
||||
- **Story Points** (falls erwähnt)
|
||||
|
||||
4. Risiken & Annahmen
|
||||
### 3. Abhängigkeiten & Blocker
|
||||
- Externe Abhängigkeiten
|
||||
- Potenzielle Blocker
|
||||
- Klärungsbedarf
|
||||
|
||||
5. Vereinbarungen / Team-Commitments
|
||||
### 4. Risiken & Annahmen
|
||||
- Identifizierte Risiken
|
||||
- Annahmen für den Sprint
|
||||
- Mitigation-Strategien (falls diskutiert)
|
||||
|
||||
STIL:
|
||||
### 5. Team-Commitments / Vereinbarungen
|
||||
- Vereinbarte Commitments
|
||||
- Rollen und Verantwortlichkeiten
|
||||
- Definition of Done (falls diskutiert)
|
||||
|
||||
## STIL:
|
||||
- Agile-konform
|
||||
- Klar & umsetzungsorientiert
|
||||
- Bullet Points bevorzugen
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Keine Zeitstempel oder Sprecherangaben
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
Reference in New Issue
Block a user