Compare commits

..

72 Commits

Author SHA1 Message Date
MikeHughes-BIN 8c0130337e Fix for windows power shell command 2025-12-19 15:31:08 +01:00
Hughes, Mike 4a7aeec869 Merge branch 'develop' into 'main'
Add start scripts for Windows and Unix environments that checks if node is...

See merge request proj-wise2526-video2document/video2document!74
2025-12-19 09:48:39 +01:00
Hughes, Mike 4f3b03f881 Merge branch 'feature/starting-scripts' into 'develop'
Add start scripts for Windows and Unix environments that checks if node is...

See merge request proj-wise2526-video2document/video2document!73
2025-12-19 09:47:31 +01:00
MikeHughes-BIN 4e4308ae51 Included starting scripts 2025-12-19 09:45:11 +01:00
MikeHughes-BIN 01913590b0 Edited the README 2025-12-19 09:36:49 +01:00
MikeHughes-BIN f750966952 Add start scripts for Windows and Unix environments that checks if node is installed, installs dependencys and starts the programm 2025-12-18 22:55:26 +01:00
Hughes, Mike 26ed7e3c58 Merge branch 'develop' into 'main'
Fixed the change speaker feature. every step till the point where its send to...

See merge request proj-wise2526-video2document/video2document!72
2025-12-17 16:58:15 +01:00
Hughes, Mike 9e05c744aa Merge branch 'feature/ui-test' into 'develop'
Feature/ui test

See merge request proj-wise2526-video2document/video2document!71
2025-12-17 16:51:18 +01:00
Verena Schulz df7ca369de Merge branch 'feature/ui-test' of gitlab.rlp.net:proj-wise2526-video2document/video2document into feature/ui-test 2025-12-17 16:42:11 +01:00
Verena Schulz b6bf178c48 First restructure changes 2025-12-17 16:42:02 +01:00
Hughes, Mike 43749fd073 Merge branch 'feature/ui-test' into 'develop'
Fixed the change speaker feature. every step till the point where its send to...

See merge request proj-wise2526-video2document/video2document!70
2025-12-17 16:15:37 +01:00
Hughes, Mike f616e06a7e Merge branch 'develop' into 'feature/ui-test'
# Conflicts:
#   main.js
2025-12-17 16:14:18 +01:00
eric.minning de43bdd190 Small fix regarding an old line which caused an error 2025-12-17 16:09:06 +01:00
eric.minning b742411dcc Fixed the display and resetting of the audio 2025-12-17 15:55:00 +01:00
eric.minning bbaab9cd21 Merge branch 'feature/ui-test' of https://gitlab.rlp.net/proj-wise2526-video2document/video2document into feature/ui-test 2025-12-17 15:29:18 +01:00
eric.minning fc8770e67f Fixed the change speaker feature. every step till the point where its send to the main functions now 2025-12-17 15:29:04 +01:00
Verena Schulz 958c9368d0 Added wrapper in step 2 2025-12-17 15:21:17 +01:00
Verena Schulz 145f91f091 centered custom_document.html 2025-12-17 14:49:32 +01:00
Verena Schulz fa429ec683 Linked Abbrechen button 2025-12-17 14:43:50 +01:00
Verena Schulz 6a8ce0a46d Linked custom_document.html with Custom docment button 2025-12-17 14:39:11 +01:00
Minning, Eric 2778626e4b Merge branch 'develop' into 'feature/ui-test'
Getting the ui-test up to date

See merge request proj-wise2526-video2document/video2document!69
2025-12-17 14:09:01 +01:00
Minning, Eric 0e746749e6 Getting the ui-test up to date 2025-12-17 14:09:00 +01:00
Hughes, Mike 853eb1a5eb Merge branch 'develop' into 'main'
New Stable Version 2.0

See merge request proj-wise2526-video2document/video2document!68
2025-12-16 19:20:19 +01:00
Hughes, Mike 3cba97a9d1 Merge branch 'fix/rename_document_type' into 'develop'
rename

See merge request proj-wise2526-video2document/video2document!67
2025-12-16 19:13:11 +01:00
MikeHughes-BIN 2900152945 rename 2025-12-16 19:11:11 +01:00
Minning, Eric 262cc2b4d6 Merge branch 'feature/ui-test' into 'develop'
Feature/ui test

See merge request proj-wise2526-video2document/video2document!66
2025-12-16 19:07:47 +01:00
eric.minning 292b893ed2 Merge branch 'feature/ui-test' of https://gitlab.rlp.net/proj-wise2526-video2document/video2document into feature/ui-test 2025-12-16 19:01:12 +01:00
eric.minning d9c76e8890 Bug fixes in the speaker selection 2025-12-16 19:01:03 +01:00
Verena Schulz 1016d2ca86 Merge branch 'feature/ui-test' of gitlab.rlp.net:proj-wise2526-video2document/video2document into feature/ui-test 2025-12-16 18:44:27 +01:00
Verena Schulz a014c62ce3 Centered download button better 2025-12-16 18:44:14 +01:00
Spanier, Pit 0a2a8e603f Merge branch 'feature/cleanup-and-tests' into 'develop'
added test for qwen3 model and added a console log for debugging purposes to...

See merge request proj-wise2526-video2document/video2document!65
2025-12-16 18:33:55 +01:00
emily 562debd883 added test for qwen3 model and added a console log for debugging purposes to the gemini test because that shit model keeps being dogshit and throwing errors about being overloaded because the dogshit company called google cant fucking manage to set up a model that doesnt shit itself the moment more than 3 people send a query at the same time, god i fucking hate google and LLMs, it is truly an insult that we have to write this dogshit software 2025-12-16 18:27:43 +01:00
emily 8927b62971 some more cleanup 2025-12-16 18:17:55 +01:00
emily b511b75db7 did some cli output cleanup, and fixed the test pipeline aswell as added a few tests 2025-12-16 18:15:40 +01:00
Minning, Eric 9b88f4719f Merge branch 'feature/ui-test' into 'develop'
Value missmatch fix

See merge request proj-wise2526-video2document/video2document!64
2025-12-16 17:35:17 +01:00
eric.minning e4770f484a Merge branch 'feature/ui-test' of https://gitlab.rlp.net/proj-wise2526-video2document/video2document into feature/ui-test 2025-12-16 17:25:54 +01:00
eric.minning 69deae9951 Fixed a value missmatch 2025-12-16 17:25:43 +01:00
Verena Schulz 6775509cf3 Merge branch 'feature/ui-test' of gitlab.rlp.net:proj-wise2526-video2document/video2document into feature/ui-test 2025-12-16 17:21:05 +01:00
Verena Schulz 3c3b27325e Centered download button 2025-12-16 17:20:55 +01:00
Hughes, Mike 0731f045ce Merge branch 'fix/rename_document_type' into 'develop'
corrected report naming again

See merge request proj-wise2526-video2document/video2document!63
2025-12-16 17:11:05 +01:00
MikeHughes-BIN b89e5ec587 corrected report naming again 2025-12-16 17:03:47 +01:00
Minning, Eric 598a8e5d34 Merge branch 'fix/rename_document_type' into 'develop'
Add requirement to retain speaker names in document templates and remove sprint planning notes

See merge request proj-wise2526-video2document/video2document!62
2025-12-16 17:00:45 +01:00
Minning, Eric 8f62b68184 Merge branch 'feature/ui-test' into 'develop'
One closing curly too much removed

See merge request proj-wise2526-video2document/video2document!61
2025-12-16 16:59:59 +01:00
MikeHughes-BIN fc041e1036 Add requirement to retain speaker names in document templates and remove sprint planning notes 2025-12-16 16:57:45 +01:00
MikeHughes-BIN 37382f7444 One closing curly too much removed 2025-12-16 16:49:46 +01:00
Hughes, Mike b05537fa70 Merge branch 'feature/ui-test' into 'develop'
Feature/ui test

See merge request proj-wise2526-video2document/video2document!59
2025-12-16 16:44:50 +01:00
Hughes, Mike 8e563187b0 Merge branch 'develop' into 'feature/ui-test'
# Conflicts:
#   main.js
2025-12-16 16:39:59 +01:00
MikeHughes-BIN 95ac7256d4 Fixed the Download button in main 2025-12-16 16:26:45 +01:00
Spanier, Pit d47cf21e9f Merge branch 'feature/38-sprecher-audio-snippets-s4-11' into 'develop'
extract speaker snippets mit main verknüpft.

See merge request proj-wise2526-video2document/video2document!60
2025-12-16 16:19:09 +01:00
Spanier, Pit 6cff6b9981 Merge branch 'develop' into 'feature/38-sprecher-audio-snippets-s4-11'
# Conflicts:
#   main.js
2025-12-16 16:18:17 +01:00
Hughes, Mike 11f9a02778 Merge branch 'develop' into 'feature/ui-test'
# Conflicts:
#   main.js
2025-12-16 15:54:00 +01:00
eric.minning 41cd8065ba Merge branch 'feature/ui-test' of https://gitlab.rlp.net/proj-wise2526-video2document/video2document into feature/ui-test 2025-12-16 15:51:18 +01:00
eric.minning c1e79b6603 Checkbox change from array to single value and value fix in html. 2025-12-16 15:50:28 +01:00
santa 0003d99041 extract speaker snippets mit main verknüpft. 2025-12-16 15:32:31 +01:00
Hughes, Mike 6a94f88e86 Merge branch 'feature/meeting_document_types' into 'develop'
Added Meeting Document Forms

See merge request proj-wise2526-video2document/video2document!55
2025-12-16 14:43:54 +01:00
MikeHughes-BIN 30f73f7bb7 Added Meeting Document Forms 2025-12-16 14:24:13 +01:00
Verena Schulz 59ac104d69 Hamburger components are clickable 2025-12-16 14:00:29 +01:00
Hughes, Mike 74439d680e Merge branch 'fix/download-button' into 'develop'
oopsies missed a </div>

See merge request proj-wise2526-video2document/video2document!53
2025-12-15 18:49:19 +01:00
MikeHughes-BIN 1b76b2e96d oopsies missed a </div> 2025-12-15 18:47:41 +01:00
Hughes, Mike 363ba2d1b5 Merge branch 'fix/download-button' into 'develop'
Enable download button functionality and improve error handling in file download

See merge request proj-wise2526-video2document/video2document!52
2025-12-15 18:43:50 +01:00
MikeHughes-BIN 6aa62ed534 Enable download button functionality and improve error handling in file download 2025-12-15 18:41:14 +01:00
Hughes, Mike cd474d7101 Merge branch 'feature/ui-test' into 'develop'
Removed a line which caused an error

See merge request proj-wise2526-video2document/video2document!51
2025-12-15 18:11:01 +01:00
eric.minning bd47a194c7 Removed a line which caused an error 2025-12-15 18:09:50 +01:00
Spanier, Pit ef080063a8 Merge branch 'feature/export-function-integration' into 'develop'
Changes to the LLMs to return a Promise (outp path) and main now calls the export process

See merge request proj-wise2526-video2document/video2document!50
2025-12-15 18:05:20 +01:00
Hughes, Mike c2c1aa1b17 Merge branch 'fix/gui-width' into 'develop'
Increased window witdth from 800px to 1200px

See merge request proj-wise2526-video2document/video2document!47
2025-12-15 17:59:12 +01:00
Hughes, Mike ee3bcdcd05 Merge branch 'feature/ui-test' into 'develop'
Implemented the function for the download button.

See merge request proj-wise2526-video2document/video2document!49
2025-12-15 17:58:33 +01:00
MikeHughes-BIN 04b2457ca3 Changes to the LLMs to return a Promise (outp path) and main now calls the export process 2025-12-15 17:58:03 +01:00
eric.minning bac6e2b7f0 Implemented the function for the download button. 2025-12-15 17:21:02 +01:00
Spanier, Pit 9760704883 Merge branch 'feature/ui-test' into 'develop'
Feature/ui test

See merge request proj-wise2526-video2document/video2document!48
2025-12-15 17:09:06 +01:00
eric.minning aee1428cb6 Changed location of the output type value in the response package 2025-12-15 17:07:07 +01:00
eric.minning 7494e13c8c Fixed an a wrong call of the speakerAudios function. 2025-12-15 17:01:04 +01:00
Hughes, Mike 283b4ed6af Merge branch 'develop' into 'main'
Implemented the general modular framework.

See merge request proj-wise2526-video2document/video2document!22
2025-11-15 15:14:24 +01:00
28 changed files with 988 additions and 650 deletions
+1
View File
@@ -24,4 +24,5 @@ job-test:
- npm install
- echo "ASSEMBLYAI_API_KEY=$apikey_assembly" > .env
- echo "GOOGLE_API_KEY=$apikey_gemini" >> .env
- echo "SAIA_API_KEY=$apikey_saia" >> .env
- npm test
+44 -81
View File
@@ -1,93 +1,56 @@
# Video2Document
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.rlp.net/proj-wise2526-video2document/video2document/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
Follow the steps below to install Video2Document (v2d):
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
### 1. Install Node.js
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
Download and install Node.js from [https://nodejs.org/en](https://nodejs.org/en)
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
### 2. Clone the Repository
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
Clone the repository using Git:
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
```bash
git clone https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
```
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
Alternatively, you can download the ZIP file and extract it manually.
## License
For open source projects, say how it is licensed.
### 3. Start the Program
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
The start scripts automatically install dependencies and launch the program. Choose the appropriate method for your operating system:
**Windows:**
```bash
start.bat
```
**Linux:**
```bash
./start.sh
```
**macOS:**
```bash
./start.sh
```
#### Alternative: Manual Installation and Start
If the start scripts don't work, you can manually install dependencies and start the program:
```bash
cd video2document
npm install
npm start
```
### 5. Install FFmpeg
Make sure that **ffmpeg** is installed on your system, as it may be required for video processing.
---
**Installation complete!** You're now ready to use Video2Document.
+161
View File
@@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Document</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f0f2f5;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: 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;
}
button {
padding: 10px 20px;
font-size: 14px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: 0.2s;
background-color: #007BFF;
color: white;
}
button:hover {
background-color: #0056b3;
}
@media (max-width: 500px) {
.buttons {
flex-direction: column;
}
.buttons button {
width: 100%;
margin-top: 10px;
}
}
#result {
margin-top: 20px;
color: #333;
word-break: break-word;
}
</style>
</head>
<body>
<div class="container">
<h1>Custom Document Generator</h1>
<label for="docName">Dokumentname:</label>
<input type="text" id="docName" placeholder="Gib hier den Dokumentnamen ein">
<label for="existingDocs">Vorhandene Dokumente auswählen (optional):</label>
<select id="existingDocs">
<option value="">-- Neues Dokument erstellen --</option>
<option value="meeting_report_001">Meeting Report 001</option>
<option value="summary_01">Summary 01</option>
<option value="project_plan_A">Project Plan A</option>
</select>
<label for="prompt">Dein Prompt:</label>
<textarea id="prompt" placeholder="Schreibe hier den Prompt für dein Dokument..."></textarea>
<div class="buttons">
<a href="index.html">
<button id="goBackBtn">Abbrechen</button>
</a>
<button id="generateBtn">Dokument speichern</button>
</div>
<div id="result"></div>
</div>
<script>
const goBackBtn = document.getElementById("goBackBtn");
const generateBtn = document.getElementById("generateBtn");
const existingDocs = document.getElementById("existingDocs");
const docNameInput = document.getElementById("docName");
const promptInput = document.getElementById("prompt");
const resultDiv = document.getElementById("result");
// Zurück zur Haupt-GUI
goBackBtn.addEventListener("click", () => {
window.electronAPI.goBackToMain();
});
// Generiere Dokument
generateBtn.addEventListener("click", () => {
const prompt = promptInput.value.trim();
let docName = docNameInput.value.trim();
const selectedExisting = existingDocs.value;
if (!prompt) {
alert("Bitte gib einen Prompt ein!");
return;
}
// Wenn ein vorhandenes Dokument ausgewählt wurde, hängt der Prompt daran
if (selectedExisting) {
docName = selectedExisting; // prompt wird an vorhandenes Dokument angehängt
} else if (!docName) {
alert("Bitte gib einen Dokumentnamen ein, wenn du ein neues Dokument erstellen möchtest!");
return;
}
// Demo-Ausgabe im Result-Div
resultDiv.innerHTML = `<strong>Dokumentname:</strong> ${docName}<br><strong>Prompt:</strong> ${prompt}`;
// Hier kannst du den Prompt an dein LLM oder Module-Handler senden
// z.B. window.submit.submit({documentName: docName, prompt: prompt})
});
</script>
</body>
</html>
+27 -26
View File
@@ -19,8 +19,8 @@
</label>
<nav class="menu1">
<li class="li1">Help</li>
<li class="li1">Language</li>
<a href="custom_document.html" class="li1">Custom document</a>
<a href="" class="li1">Help</a>
</nav>
</nav>
</section>
@@ -57,23 +57,28 @@
</div>
<div class="step" id="step2" style="display:none;">
<div class="labelDiv" id="labelDiv">
<div class="KI-wrapper">
<label id="labelKI">Select ki:</label>
<label id="labelTranscription">Select transcription:</label>
<label id="labelType">Select type:</label>
<label id="labelLanguage">Select language:</label>
<img id="labelLanguageFlag" src="flags/united-kingdom-flag-png-large.jpg" width="20" height="10" >
<select name="ai_type" id="ai_type"></select>
</div>
<div class="dropdownMenus" id="dropdownMenus">
<select name="ai_type" id="ai_type">
</select>
<select name="transkript_type" id="transkript_type">
</select>
<div class="transcript-wrap">
<label id="labelTranscription">Select transcription:</label>
<select name="transkript_type" id="transkript_type"></select>
</div>
<div class="type-wrapper">
<label id="labelType">Select type:</label>
<select name="output_type" id="output_type">
<option value="pdf">.pdf</option>
<option value="word">.word</option>
<option value="txt">.txt</option>
</select>
</div>
<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>
</div>
@@ -83,23 +88,23 @@
<div class="checkbox-group">
<label id="checkbox-label" for="checkbox-group">Choose prefered document style:</label>
<div class="checkbox-container">
<input type="checkbox" name ="docFormat" id="docFormat" value="Meeting report">
<input type="checkbox" name ="docFormat" id="docFormat" value="followup-report">
<label id="label_format" for="docFormat">Follow-up Report</label>
</div>
<div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary1" value="Summary with timestamps">
<input type="checkbox" name="docFormat" id="docFormatSummary1" value="agenda">
<label id="label_summary" for="docFormatSummary">Agenda</label>
</div>
<div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary2" value="Summary with timestamps">
<input type="checkbox" name="docFormat" id="docFormatSummary2" value="result-protocol">
<label id="label_summary" for="docFormatSummary">Resultprotocol</label>
</div>
<div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatSummary3" value="Summary with timestamps">
<input type="checkbox" name="docFormat" id="docFormatSummary3" value="sprint-planning">
<label id="label_summary" for="docFormatSummary">Sprint Planning Note</label>
</div>
<div class="checkbox-container">
<input type="checkbox" name="docFormat" id="docFormatCustom" value="Summary with timestamps">
<input type="checkbox" name="docFormat" id="docFormatCustom" value="custom">
<select name="ai_type" id="ai_type">
<option>nichts</option>
</select>
@@ -129,7 +134,6 @@
<div class="speakerView" id="speakerView">
<label id="labelSpeaker">Select Speaker:</label>
<select name="cur_speaker" id="cur_speaker">
<options>Stefan</options>
</select>
</div>
<div class="speakerAudio" id="speakerAutio">
@@ -142,17 +146,14 @@
<label id="labelSpeakerWriter">Write name:</label>
<input type="text" id="newSpeaker">
</div>
<button id="speakerLocker" onclick="rewriteSpeakerName()">Rename Speaker</button>
<button id="speakerResender" onclick="sendSpeakerPackages()">Rewrite document</button>
<div class="speakerButton-group">
<button id="speakerLocker" onclick="rewriteSpeakerName()">Rename Speaker</button>
<button id="speakerResender" onclick="sendSpeakerPackages()">Rewrite document</button>
</div>
</div>
<div class="step" id="step6" style="display:none;">
<button class="download-btn" id="downloadButton" onclick="" disabled>Download</button>
<div class="progressbar" id="progressbar">
<div class="progress_fill"></div>
<span class="progress_text">0%</span>
</div>
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button>
</div>
</div>
+6 -1
View File
@@ -23,9 +23,14 @@ try {
speakerAudios: (callback) => ipcRenderer.on('speakerAudios', callback)
})
contextBridge.exposeInMainWorld("submitSpeaker", {
submitSpeaker: (speaker_names) => {ipcRenderer.send("speaker_submit", speaker_names)}
speaker_submit: (speaker_names) => {ipcRenderer.send("speaker_submit", speaker_names)}
})
contextBridge.exposeInMainWorld("download", {
file_download: () => {ipcRenderer.send("file_download")}
})
ipcRenderer.on("error", (event, err) => {alert(err)})
} catch (error) {
console.log("Error in preload.js");
+16 -21
View File
@@ -19,7 +19,6 @@ uploadContainer.addEventListener("drop", (e) => {
const testEndings = [".mp4", ".mov", ".avi", ".mkv"];
var pathToLower = filePath.toLowerCase();
if(testEndings.some(e => pathToLower.endsWith(e))){
document.getElementById("progressbar").style.visibility = "visible";
const files1 = e.dataTransfer.files;
handleFiles(files1);
}else{
@@ -28,12 +27,12 @@ uploadContainer.addEventListener("drop", (e) => {
} catch (error) {
console.log("Error in renderer.js with the listerner for the drop function");
console.log(error);
}
})
window.addEventListener('load', async (e) => {
try {
console.log("test");
loadLanguageOptions();
const value = await window.onStartup.getModuleNames();
loadAiOptions(value.ai_modules);
@@ -117,7 +116,7 @@ docFormat.addEventListener("change", (e) =>{
} catch (error) {
}
})
});
docFormatSummary1.addEventListener("change", (e) =>{
try {
if(docFormatSummary1.checked){
@@ -129,7 +128,7 @@ docFormatSummary1.addEventListener("change", (e) =>{
} catch (error) {
}
})
});
docFormatSummary2.addEventListener("change", (e) =>{
try {
if(docFormatSummary2.checked){
@@ -141,7 +140,7 @@ docFormatSummary2.addEventListener("change", (e) =>{
} catch (error) {
}
})
});
docFormatSummary3.addEventListener("change", (e) =>{
try {
if(docFormatSummary3.checked){
@@ -153,7 +152,7 @@ docFormatSummary3.addEventListener("change", (e) =>{
} catch (error) {
}
})
});
docFormatCustom.addEventListener("change", (e) =>{
try {
if(docFormatCustom.checked){
@@ -165,25 +164,21 @@ docFormatCustom.addEventListener("change", (e) =>{
} catch (error) {
}
})
});
//Speaker change listener
cur_speaker.addEventListener("change", (e) =>{
try {
document.getElementById("speakerAudioViewer").src = valy[e.target.value].source;
document.getElementById("speakerAudioViewer").src = speakerAudios[document.getElementById("cur_speaker").value].src;
} catch (error) {
}
})
});
window.electron.speakerAudios((event, arg) => {
try {
setSpeakerAudiosValue(arg);
loadSpeakerOptions(arg);
} catch (error) {
}
})
window.audios.speakerAudios((event, arg) => {
loadSpeakerOptions(arg);
setSpeakerAudiosValue(arg);
});
window.electron.progress((event, arg) => {
if(arg.curstep == 1){
@@ -207,7 +202,7 @@ function setCircleOne(){
} catch (error) {
}
}
};
function setCircleZwo(){
try {
if(document.getElementById("box2").style.backgroundColor == "green"){
@@ -219,7 +214,7 @@ function setCircleZwo(){
}
}
};
function setCircleThree(){
try {
if(document.getElementById("box3").style.backgroundColor == "green"){
@@ -231,7 +226,7 @@ function setCircleThree(){
}
}
};
function setCircleFour(){
try {
if(document.getElementById("box4").style.backgroundColor == "green"){
@@ -242,7 +237,7 @@ function setCircleFour(){
} catch (error) {
}
}
};
+33 -25
View File
@@ -25,18 +25,15 @@ function checkBoxes() {
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
var pathToLower = pathTest.toLowerCase();
if(testEndings.some(e => pathToLower.endsWith(e))){
document.getElementById("progressbar").style.visibility = "visible";
//assembly of the json for the main
const selectedStyles = [checkedCounter];
var iter = 0;
checkboxes.forEach(function(checkbox){
if(checkbox.checked){
console.log(checkbox.value);
selectedStyles[iter] = {iter: checkbox.value};
iter++;
}
});
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";
@@ -49,15 +46,15 @@ function checkBoxes() {
const sendingPackage = {
"video": {
"module":"extraction-video-to-audio",
"inputVideoPath": pathTest,
"outputType": outputType.value
"inputVideoPath": pathTest
},
"transcription": {
"module": transcriptionType.value
},
"document": {
"module":aiType.value,
"styles": selectedStyles
"type": typeCheckbox,
"outputType": outputType.value
}
};
window.submit.submit(sendingPackage)
@@ -105,7 +102,6 @@ function changeLanguage(language) {
function handleFiles(files) {
try {
if (files.length > 0) {
document.getElementById("progressbar").style.visibility = "visible";
const file = files[0];
if (file.type.startsWith('video/')) {
const filePath = window.explorer.onFileDrop(files[0])
@@ -215,16 +211,21 @@ function loadLanguageOptions(){
//function to load speaker options to the drop down list
function loadSpeakerOptions(options){
try {
var menu = document.getElementById('speaker_option');
var menu = document.getElementById('cur_speaker');
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 = options.keys();
for(i = 0; i < options.length; i++){
object_holdy = Object.keys(options);
for(i = 0; i < object_holdy.length; i++){
choice = document.createElement('option');
choice.textContent = options[object_holdy[i]].name;
choice.value = options[object_holdy[i]].name;
choice.value = object_holdy[i];
menu.appendChild(choice);
}
document.getElementById("speakerAudioViewer").src = options.speakerA.src;
} catch (error) {
console.log("Error in script.js loadSpeakerOptions function");
console.log(error);
@@ -285,7 +286,7 @@ function showStep(stepNumber) {
return;
}
steps.forEach(step => step.style.display = "none");
document.getElementById("step" + stepNumber).style.display = "block";
document.getElementById("step" + stepNumber).style.display = "flex";
stepButtons.forEach(btn => btn.classList.remove("active"));
document.querySelector(`.step-item[data-step="${stepNumber}"]`).classList.add("active");
@@ -306,7 +307,7 @@ function setSpeakerAudiosValue(valy){
try {
speakerAudios = valy;
speakerRewriten = valy;
document.getElementById("speakerAudioViewer").src = valy.speakerA.source;
document.getElementById("speakerAudioViewer").src = valy.speakerA.src;
} catch (error) {
}
@@ -314,19 +315,26 @@ function setSpeakerAudiosValue(valy){
function rewriteSpeakerName(){
try {
var tempy = document.getElementById("cur_speaker").textContent;
speakerAudios[tempy].name = document.getElementById("newSpeaker").textContent;
document.getElementById("cur_speaker").textContent = document.getElementById("newSpeaker").textContent;
var tempy = document.getElementById("cur_speaker").value;
speakerAudios[tempy].name = document.getElementById("newSpeaker").value;
loadSpeakerOptions(speakerAudios);
} catch (error) {
console.log("\n\n\n" + error + "\n\n\n")
}
}
function sendSpeakerPackages(){
try {
window.sendSpeakerPackages(speakerAudios);
window.submitSpeaker.speaker_submit(speakerAudios);
} catch (error) {
}
}
function fileDownload() {
try {
window.download.file_download();
} catch (error) {
console.error("Download failed:", error);
}
}
+45 -11
View File
@@ -17,7 +17,6 @@ body {
transform: translate(-50%, -50%);
margin: 0;
z-index: 20;
}
#h1-wrapper {
@@ -109,6 +108,14 @@ body {
background-color: #0056b3;
}
#step2 {
gap: 30px;
}
.KI-wrapper {
margin-top: 40px;
}
input[type="file"] {
display: none;
}
@@ -176,11 +183,10 @@ input[type="file"] {
.submit-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 10px 20px;
margin-left: 80px;
margin-top: 30px;
margin-bottom: 10px;
margin: 130px auto 10px auto;
background-color: #007BFF;
color: white;
border: none;
@@ -294,7 +300,6 @@ input[type="file"] {
margin-top: 70px;
display: flex;
flex-direction: column;
justify-content: center;
min-height: 400px;
}
@@ -420,7 +425,6 @@ li {
border-radius: 5px;
background-color: #1C3B69;
margin: 0;
display: -ms-grid;
display: grid;
grid-template-rows: 1fr repeat(4, 0.5fr);
grid-row-gap: 25px;
@@ -436,19 +440,21 @@ li {
-webkit-transition: all 0.3s ease;
}
.menu1 li:first-child {
.menu1 a:first-child {
margin-top: 30px;
}
.menu1 li:last-child {
.menu1 a:last-child {
margin-bottom: 30px;
}
.li1 {
color: #fff;
width: 100%;
margin: 0;
padding: 10px 0;
padding: 10px 0px;
font: 700 20px 'Oswald', sans-serif;
text-decoration: none;
}
.li1:hover {
@@ -463,12 +469,29 @@ li {
font-size: larger;
}
#step4 {
align-items: center;
}
#step5 {
align-items: flex-start;
}
.button-group {
display: flex;
gap: 12px;
justify-content: center;
margin-top: 10px;
}
.download-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 10px 20px;
margin-left: 80px;
margin-top: 30px;
margin-left: auto;
margin-right: 0px;
margin-top: 130px;
margin-bottom: 10px;
background-color: #007BFF;
color: white;
@@ -477,3 +500,14 @@ li {
cursor: pointer;
font-size: 14px;
}
#speakerLocker, #speakerResender{
padding: 10px 20px;
margin: 20px auto;
background-color: #007BFF;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
}
+38 -33
View File
@@ -124,16 +124,28 @@ electron.ipcMain.handle('get-module-names', async () => {
// mainWindow.webContents.send("modules", module_array)
// })
var globalArgs = {}
var globalFinalHtmlPath = ""
electron.ipcMain.on("file_submit", async (event, args) => {
try {
globalArgs = args
let curstep = 0
let totalsteps = 3 + args.document.styles.length
let totalsteps = 4
if(args.document.styles.length == 0)
throw new Error("At least one Document Style needed");
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];
if (!templateFile) {
throw new Error("Unknown document type: " + args.document.type);
}
console.log(args);
let audiopath = ""
@@ -182,45 +194,38 @@ electron.ipcMain.on("file_submit", async (event, args) => {
console.log("\n\n Running the LLM module");
// TODO implement documentation module
// This code handles the Text to Document processing module call
for (let i = 0; i < args.document.styles.length; i++) {
console.log(`\n\n Running the LLM for Document Style ${i+1}`);
await mapFunctions.get("module-handler").function(args.document.module, {inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/standard_meeting_report.txt", language: "en"}).then(resp => {
console.log(resp);
transcriptpath = resp
curstep++
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
}).catch(err => {
mainWindow.webContents.send("error", err)
return
})
}
console.log(`\n\n Running the LLM for Document Style ${args.document.type}`);
// TODO actually implement this functionality
// Module to get the first few lines for each speaker to send to the frontend
// await mapFunctions.get("speaker-getter-idfk").function(transcriptpath).then(resp => {
// console.log(resp);
// transcriptpath = resp
// curstep++
// mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
// // {
// // speakerA: {source: "Pfad zur Audio File"},
// // speakerB:.....
// // }
mainWindow.webContents.send("speakers", {speakerA:"pfad1", speakerB:"pfad2"})
// }).catch(err => {
// mainWindow.webContents.send("error", err)
// return
// })
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)
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)
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() => {
console.log("\n\n\nJa also hier kam was an \n\n\n");
})
let q =
{
+6 -8
View File
@@ -15,7 +15,7 @@
"dotenv": "^17.2.3",
"electron": "^39.1.1",
"express": "^5.1.0",
"ffmpeg-static": "^5.2.0",
"ffmpeg-static": "^5.3.0",
"fluent-ffmpeg": "^2.1.3",
"html-to-docx": "^1.8.0",
"mocha": "^11.7.5",
@@ -450,7 +450,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz",
"integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==",
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -1306,8 +1305,7 @@
"version": "0.0.1534754",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1534754.tgz",
"integrity": "sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==",
"license": "BSD-3-Clause",
"peer": true
"license": "BSD-3-Clause"
},
"node_modules/diff": {
"version": "4.0.2",
@@ -1773,9 +1771,9 @@
}
},
"node_modules/ffmpeg-static": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.2.0.tgz",
"integrity": "sha512-WrM7kLW+do9HLr+H6tk7LzQ7kPqbAgLjdzNE32+u3Ff11gXt9Kkkd2nusGFrlWMIe+XaA97t+I8JS7sZIrvRgA==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.3.0.tgz",
"integrity": "sha512-H+K6sW6TiIX6VGend0KQwthe+kaceeH/luE8dIZyOP35ik7ahYojDuqlTV1bOrtEwl01sy2HFNGQfi5IDJvotg==",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -1832,6 +1830,7 @@
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz",
"integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT",
"dependencies": {
"async": "^0.2.9",
"which": "^1.1.1"
@@ -4205,7 +4204,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
+1 -1
View File
@@ -6,7 +6,7 @@
"dotenv": "^17.2.3",
"electron": "^39.1.1",
"express": "^5.1.0",
"ffmpeg-static": "^5.2.0",
"ffmpeg-static": "^5.3.0",
"fluent-ffmpeg": "^2.1.3",
"html-to-docx": "^1.8.0",
"mocha": "^11.7.5",
@@ -0,0 +1,102 @@
const ffmpeg = require("fluent-ffmpeg");
const ffmpegPath = require("ffmpeg-static");
ffmpeg.setFfmpegPath(ffmpegPath);
module.exports = {
name: "extract-speaker-snippets",
type: "audio",
displayname: "Extract Speaker Snippets",
async function(parameter) {
return new Promise(async (resolve, reject) => {
let output = {}
// console.log("Extract Speaker Snippets\n");
// Pfade
const AUDIO_PATH = parameter.audioPath; // Gesamt-Audio
const JSON_PATH = parameter.jsonPath; // json summary
const OUTPUT_DIR = path.join(__dirname, "/../../../storage/audio/speakerSnippets");
if (!AUDIO_PATH || !JSON_PATH) {
// console.error("no audioPath or jsonPath available");
reject(new Error("no audioPath or jsonPath available"));
return;
}
// Output-Ordner
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
// JSON laden
let entries;
try {
entries = JSON.parse(fs.readFileSync(JSON_PATH, "utf8"));
} catch (err) {
// console.error("JSON reading failed", err);
reject(new Error(err));
return;
}
if (!Array.isArray(entries)) {
// console.error("JSON is not an Array");
reject(new Error("JSON is not an Array"));
return;
}
// Pro Speaker genau EINEN Satz merken
const speakerMap = {};
for (const item of entries) {
if (!speakerMap[item.speaker]) {
speakerMap[item.speaker] = item;
}
}
// FFmpeg pro Speaker ausführen (sequenziell)
for (const speaker of Object.keys(speakerMap)) {
const data = speakerMap[speaker];
// ms → Sekunden
const startSec = data.start / 1000;
const durationSec = (data.end - data.start) / 1000;
if (durationSec <= 0) {
// console.log(`invalid times for Speaker ${speaker}`);
continue;
}
const outFile = path.join(OUTPUT_DIR, `speaker_${speaker}.wav`);
try {
await new Promise((res, rej) => {
ffmpeg(AUDIO_PATH)
.setStartTime(startSec)
.setDuration(durationSec)
.output(outFile)
.on("end", () => {
output[`speaker${speaker}`] = {src: outFile, name: `speaker${speaker}`}
// console.log(`Snippet erstellt: speaker_${speaker}.wav`);
res();
})
.on("error", (err) => {
// console.error(`FFmpeg Fehler (${speaker})`, err.message);
rej(err);
return
})
.run();
});
} catch (error) {
reject(error)
return
}
}
resolve(output)
// console.log("\nAlle Speaker-Snippets erstellt\n");
})
}
};
+21 -18
View File
@@ -30,25 +30,28 @@ async function showSaveDialog(defaultName, format) {
throw err;
}
} else if (platform === 'win32') {
// Windows
const powershell = `
Add-Type -AssemblyName System.Windows.Forms
$dialog = New-Object System.Windows.Forms.SaveFileDialog
$dialog.FileName = "${defaultName}.${format}"
$dialog.Filter = "${format.toUpperCase()} Dateien (*.${format})|*.${format}|Alle Dateien (*.*)|*.*"
$dialog.Title = "Dokument speichern als"
$result = $dialog.ShowDialog()
if ($result -eq 'OK') { $dialog.FileName }
`;
const safeName = decodeURIComponent(defaultName);
try {
const result = execSync(`powershell -Command "${powershell.replace(/\n/g, '; ')}"`, {
encoding: 'utf8'
});
return result.trim() || null;
} catch (err) {
throw err;
}
const powershell = `
Add-Type -AssemblyName System.Windows.Forms;
$dialog = New-Object System.Windows.Forms.SaveFileDialog;
$dialog.FileName = '${safeName}.${format}';
$dialog.Filter = '${format.toUpperCase()} Dateien (*.${format})|*.${format}|Alle Dateien (*.*)|*.*';
$dialog.Title = 'Dokument speichern als';
$result = $dialog.ShowDialog();
if ($result -eq 'OK') { $dialog.FileName }
`;
try {
const result = execSync(
`powershell -NoProfile -Command "${powershell.replace(/\r?\n/g, ' ')}"`,
{ encoding: 'utf8' }
);
return result.trim() || null;
} catch (err) {
if (err.status === 1) return null; // User cancelled
throw new Error("Save dialog failed: " + err.message);
}
} else {
// Linux - zenity oder kdialog
try {
+63 -57
View File
@@ -1,7 +1,7 @@
const fs = require('fs');
const path = require('path');
// const fs = require('fs');
// const path = require('path');
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
@@ -9,8 +9,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
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; //URL for the REST call, used model and action
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action
const module_exports = {
name: "llm-saia_openai_gpt",
@@ -19,66 +18,73 @@ const module_exports = {
description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform",
async function(parameter) {
try {
console.log("SAIA OpenAI GPT module invoked with parameters:", parameter);
return new Promise(async (resolve, reject) => {
try {
// console.log("SAIA OpenAI GPT module invoked with parameters:", parameter);
await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
parameter.inputTranscriptPath, // Path to input transcript file
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
parameter.language // Language for the document which is chosen in the front end by the user
);
resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
parameter.inputTranscriptPath, // Path to input transcript file
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
parameter.language // Language for the document which is chosen in the front end by the user
));
} catch (error) {
// console.error("Error in SAIA OpenAI GPT module:", error);
reject(error)
}
})
} catch (error) {
console.error("Error in SAIA OpenAI GPT module:", error);
}
},
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
try {
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
return new Promise(async(resolve, reject) => {
try {
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
// --- REST CALL ---
const response = await fetch(SAIA_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${SAIA_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "openai-gpt-oss-120b",
messages: [
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
{ role: "user", content: promptText }
],
temperature: 0
})
});
// return
// --- REST CALL ---
const response = await fetch(SAIA_URL, { //safe model response in variable
method: "POST",
headers: {
"Authorization": `Bearer ${SAIA_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "openai-gpt-oss-120b",
messages: [
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
{ role: "user", content: promptText }
],
temperature: 0
})
});
if (!response.ok) { //ok is true when a response was successful
const text = await response.text();
throw new Error(`SAIA API error (${response.status}): ${text}`);
if (!response.ok) { //ok is true when a responce was successfull
const text = await response.text();
throw new Error(`SAIA API error (${response.status}): ${text}`);
}
const data = await response.json();
// Get generated text from response or default to empty string (if null)
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
const output = data.choices?.[0]?.message?.content || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
// console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
// console.log("Generated document written to:", outPath);
resolve(outPath)
} catch (error) {
// console.error("Error generating SAIA content:", error);
reject(error)
}
const data = await response.json();
// Get generated text from response or default to empty string (if null)
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
const output = data.choices?.[0]?.message?.content || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
console.log("Generated document written to:", outPath);
} catch (error) {
console.error("Error generating SAIA content:", error);
}
})
}
};
+1 -1
View File
@@ -71,7 +71,7 @@ const module_exports = {
const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
// console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
// console.log("Generated document written to:", outPath);
-130
View File
@@ -1,130 +0,0 @@
const fs = require('fs');
const path = require('path');
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
}
// Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here"
const SAIA_API_KEY = process.env.SAIA_API_KEY;
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action
const module_exports = {
name: "qwen3-235b-a22b",
type: "llm",
displayname: "QWEN 3 235B",
description: "Generates documents using QWEN 3 235B via SAIA platform",
async function(parameter) {
try {
console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language
parameter.inputTranscriptPath, // Path to input transcript file
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
parameter.language // Language for the document which is chosen in the front end by the user
);
} catch (error) {
console.error("Error in SAIA QWEN 3 235B module:", error);
}
},
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
try {
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed
// --- REST CALL ---
const response = await fetch(SAIA_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${SAIA_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "qwen3-235b-a22b",
messages: [
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
{ role: "user", content: promptText }
],
temperature: 0
})
});
if (!response.ok) { // ok is true when a response was successful
const text = await response.text();
throw new Error(`SAIA API error (${response.status}): ${text}`);
}
const data = await response.json();
// Get generated text from response or default to empty string (if null)
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
const output = data.choices?.[0]?.message?.content || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
console.log("Generated document written to:", outPath);
} catch (error) {
console.error("Error generating SAIA content:", error);
}
}
};
module.exports = module_exports;
// CLI Mode: Allow direct execution
if (require.main === module) {
(async () => {
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node qwen3.js <transcriptPath> <documentTypePath> [language]");
console.error("Example: node qwen3.js ./transcript.json ./docType.txt de");
process.exit(1);
}
const [transcriptPath, documentTypePath, language] = args;
// Check if API key is set
if (!SAIA_API_KEY) {
console.error("ERROR: SAIA_API_KEY environment variable is not set!");
console.error("Please set it with: export SAIA_API_KEY='your_api_key_here'");
process.exit(1);
}
// Check if files exist
if (!fs.existsSync(transcriptPath)) {
console.error(`ERROR: Transcript file not found: ${transcriptPath}`);
process.exit(1);
}
if (!fs.existsSync(documentTypePath)) {
console.error(`ERROR: Document type file not found: ${documentTypePath}`);
process.exit(1);
}
console.log("Starting document generation...");
console.log(`Transcript: ${transcriptPath}`);
console.log(`Document Type: ${documentTypePath}`);
console.log(`Language: ${language || 'en (default)'}`);
await module_exports.createDocumentFromTranscript(
transcriptPath,
documentTypePath,
language || 'en'
);
console.log("Done!");
})();
}
+136
View File
@@ -0,0 +1,136 @@
const fs = require('fs');
const path = require('path');
const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
}
// Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here"
const SAIA_API_KEY = process.env.SAIA_API_KEY;
const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action
const module_exports = {
name: "qwen3-235b-a22b",
type: "llm",
displayname: "QWEN 3 235B",
description: "Generates documents using QWEN 3 235B via SAIA platform",
async function(parameter) {
return new Promise(async (resolve, reject) => {
try {
// console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
parameter.inputTranscriptPath, // Path to input transcript file
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
parameter.language // Language for the document which is chosen in the front end by the user
));
} catch (error) {
// console.error("Error in SAIA QWEN 3 235B module:", error);
reject(error)
}
})
},
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
return new Promise(async(resolve, reject) => {
try {
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
// --- REST CALL ---
const response = await fetch(SAIA_URL, { //safe model response in variable
method: "POST",
headers: {
"Authorization": `Bearer ${SAIA_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "qwen3-235b-a22b",
messages: [
{ role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." },
{ role: "user", content: promptText }
],
temperature: 0
})
});
if (!response.ok) { //ok is true when a responce was successfull
const text = await response.text();
throw new Error(`SAIA API error (${response.status}): ${text}`);
}
const data = await response.json();
// Get generated text from response or default to empty string (if null)
// SAIA uses OpenAI-compatible structure: data.choices[x].message.content
const output = data.choices?.[0]?.message?.content || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
// console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
// console.log("Generated document written to:", outPath);
resolve(outPath)
} catch (error) {
// console.error("Error generating SAIA content:", error);
reject(error)
}
})
}
};
module.exports = module_exports;
// CLI Mode: Allow direct execution
if (require.main === module) {
(async () => {
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node qwen3.js <transcriptPath> <documentTypePath> [language]");
console.error("Example: node qwen3.js ./transcript.json ./docType.txt de");
process.exit(1);
}
const [transcriptPath, documentTypePath, language] = args;
// Check if API key is set
if (!SAIA_API_KEY) {
console.error("ERROR: SAIA_API_KEY environment variable is not set!");
console.error("Please set it with: export SAIA_API_KEY='your_api_key_here'");
process.exit(1);
}
// Check if files exist
if (!fs.existsSync(transcriptPath)) {
console.error(`ERROR: Transcript file not found: ${transcriptPath}`);
process.exit(1);
}
if (!fs.existsSync(documentTypePath)) {
console.error(`ERROR: Document type file not found: ${documentTypePath}`);
process.exit(1);
}
console.log("Starting document generation...");
console.log(`Transcript: ${transcriptPath}`);
console.log(`Document Type: ${documentTypePath}`);
console.log(`Language: ${language || 'en (default)'}`);
await module_exports.createDocumentFromTranscript(
transcriptPath,
documentTypePath,
language || 'en'
);
console.log("Done!");
})();
}
+1
View File
@@ -10,6 +10,7 @@ module.exports = {
// let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav');
// let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'});
// let snippets = await mapFunctions.get("extract-speaker-snippets").function({audioPath:'/Users/santa/Proj25/video2document/storage/audio/KittyKat.wav', jsonPath1: '/Users/santa/Proj25/video2document/storage/transcriptionSummaries/KittyKat-1765806474958.json' });
+23
View File
@@ -0,0 +1,23 @@
@echo off
cd /d %~dp0
:: Prüfen ob Node.js installiert ist
where node >nul 2>nul
if %errorlevel% neq 0 (
echo Node.js ist nicht installiert.
pause
exit /b 1
)
echo Node.js gefunden:
node -v
npm install
if %errorlevel% neq 0 (
echo npm install fehlgeschlagen.
pause
exit /b 1
)
npm start
pause
Executable
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# Prüfen ob Node.js installiert ist
if ! command -v node >/dev/null 2>&1; then
echo "Node.js ist nicht installiert."
exit 1
fi
echo "Node.js gefunden: $(node -v)"
# Abhängigkeiten installieren
npm install || exit 1
# Projekt starten
npm start
BIN
View File
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
Du bist ein erfahrener Moderator und Projektmanager.
AUFGABE:
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem folgenden Transkript.
ANFORDERUNGEN:
- Rekonstruiere die tatsächlichen Themenblöcke
- Ordne sie logisch und chronologisch
- Fasse ähnliche Diskussionen zusammen
- Keine irrelevanten Details aufnehmen
STRUKTUR:
- Titel der Agenda
- Ziel des Meetings (12 Sätze)
- Agenda-Punkte (nummeriert)
- 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
TRANSKRIPT:
+22
View File
@@ -0,0 +1,22 @@
Du bist ein intelligenter Dokumenten-Generator.
AUFGABE:
Erstelle ein individuelles Dokument basierend auf:
1) dem Meeting-Transkript
2) der zusätzlichen Nutzeranweisung
WICHTIG:
- Priorisiere die Nutzeranweisung
- Nutze das Transkript als Wissensquelle
- Struktur, Tonalität und Detailgrad 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
FORMAT:
- Passe Struktur und Stil an den Nutzerwunsch an
- Klare Überschriften
- Keine Sprecher- oder Zeitangaben
TRANSKRIPT & NUTZERANWEISUNG:
+45
View File
@@ -0,0 +1,45 @@
Du bist ein professioneller Meeting-Analyst und Business Writer.
AUFGABE:
Erstelle einen strukturierten Follow-up Report basierend auf dem folgenden 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
STRUKTUR DES DOKUMENTS:
1. Titel & Metadaten
- Meetingtitel (ableiten)
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben“)
- Teilnehmer (zusammengefasst)
2. Executive Summary (max. 5 Bullet Points)
3. Besprochene Themen
- Thema
- Kernaussagen
- Relevante Erkenntnisse
4. Entscheidungen
- Entscheidung
- Kontext / Begründung
5. Action Items
- Aufgabe
- Verantwortlich (falls ableitbar)
- Ziel / Zweck
6. Offene Fragen & Risiken
STIL:
- Überschriften klar strukturiert
- Bullet Points bevorzugen
- Präzise, keine Umgangssprache
TRANSKRIPT:
+27
View File
@@ -0,0 +1,27 @@
Du bist ein professioneller Protokollführer.
AUFGABE:
Erstelle ein Ergebnisprotokoll basierend auf dem Meeting-Transkript.
FOKUS:
- Ergebnisse statt Diskussionen
- Entscheidungen, Beschlüsse, Vereinbarungen
- Klare, überprüfbare Aussagen
STRUKTUR:
1. Meeting-Informationen
2. Ergebnisse je Thema
- Thema
- Ergebnis / Beschluss
3. Entscheidungen
4. Aufgaben & Verantwortlichkeiten
5. Offene Punkte
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
TRANSKRIPT:
@@ -0,0 +1,35 @@
Du bist ein erfahrener Scrum Master.
AUFGABE:
Erstelle Sprint Planning Notes aus dem folgenden Meeting-Transkript.
FOKUS:
- Sprint-Ziele
- User Stories / Tasks
- Abhängigkeiten
- Risiken
- Commitments
STRUKTUR:
1. Sprint Overview
- Sprint-Ziel
- Zeitraum (falls erwähnt)
2. Geplante Arbeit
- User Story / Task
- Beschreibung
- Akzeptanzkriterien (falls ableitbar)
3. Abhängigkeiten & Blocker
4. Risiken & Annahmen
5. Vereinbarungen / Team-Commitments
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
TRANSKRIPT:
@@ -1,217 +0,0 @@
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
Output ONLY the final .md document — no meta comments, no explanations.
Follow exactly the STRUCTURE defined below.
Follow exactly the STYLE rules.
Use timestamps in HH:MM:SS format.
If information is missing, use: Unclear:<reason>.
==================== STRUCTURE & RULES ====================
{
"FORMAT": "HTML",
"STRUCTURE": {
"titlepage": [
"title",
"date",
"start",
"end",
"duration",
"location",
"host",
"participants"
],
"toc": "[section](#anchor) — HH:MM:SS",
"section": {
"h2": "<topic> — HH:MM:SS",
"summary": "exactly 1 concise sentence",
"key_points": "maximum 5 bullet points; quotes optional",
"decisions": "list items formatted as: decision text | owner | due date",
"actions": "HTML table: id | task | owner | due | status"
},
"exec_summary": "exactly 3 short sentences",
"consolidated": [
"decisions",
"actions"
],
"appendix": "optional"
},
"STYLE": {
"tone": "neutral, concise, professional",
"ts_format": "HH:MM:SS",
"no_meta": true
},
"PROCESS": {
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
"speakers": "use names if available; else Speaker X",
"long_transcripts": "split → summarize → merge",
"unclear": "Unclear:<reason>"
},
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
}
============================================================
Insert all generated content into the following HTML TEMPLATE:
# {{title}}
**Date:** {{date}}
**Start:** {{start}}
**End:** {{end}}
**Duration:** {{duration}}
**Location:** {{location}}
**Host:** {{host}}
**Participants:** {{participants}}
---
## Table of Contents
{{toc}}
---
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
Output ONLY the final .md document — no meta comments, no explanations.
Follow exactly the STRUCTURE defined below.
Follow exactly the STYLE rules.
Use timestamps in HH:MM:SS format.
If information is missing, use: UNKLAR:<reason>.
==================== STRUCTURE & RULES ====================
{
"FORMAT": "HTML",
"STRUCTURE": {
"titlepage": [
"title",
"date",
"start",
"end",
"duration",
"location",
"host",
"participants"
],
"toc": "[section](#anchor) — HH:MM:SS",
"section": {
"h2": "<topic> — HH:MM:SS",
"summary": "exactly 1 concise sentence",
"key_points": "maximum 5 bullet points; quotes optional",
"decisions": "list items formatted as: decision text | owner | due date",
"actions": "HTML table: id | task | owner | due | status"
},
"exec_summary": "exactly 3 short sentences",
"consolidated": [
"decisions",
"actions"
],
"appendix": "optional"
},
"STYLE": {
"tone": "neutral, concise, professional",
"ts_format": "HH:MM:SS",
"no_meta": true
},
"PROCESS": {
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
"speakers": "use names if available; else Speaker X",
"long_transcripts": "split → summarize → merge",
"unclear": "UNKLAR:<reason>"
},
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
}
============================================================
Insert all generated content into the following HTML TEMPLATE:
# {{title}}
**Date:** {{date}}
**Start:** {{start}}
**End:** {{end}}
**Duration:** {{duration}}
**Location:** {{location}}
**Host:** {{host}}
**Participants:** {{participants}}
---
## Table of Contents
{{toc}}
---
## Executive Summary
{{exec_summary}}
---
## Sections
{{sections}}
---
## Consolidated Decisions
{{consolidated_decisions}}
---
## Consolidated Actions
{{consolidated_actions}}
---
## Appendix
{{appendix}}
============================================================
Final Requirement:
Output ONLY the completed HTML meeting report.
## Executive Summary
{{exec_summary}}
---
## Sections
{{sections}}
---
## Consolidated Decisions
{{consolidated_decisions}}
---
## Consolidated Actions
{{consolidated_actions}}
---
## Appendix
{{appendix}}
============================================================
Final Requirement:
Output ONLY the completed HTML meeting report.
+89 -16
View File
@@ -21,6 +21,7 @@ let audiopath
let transcriptPath
let summarizePath
let llmpath
let speakers
describe("Unit Tests", function() {
@@ -34,7 +35,7 @@ describe("Unit Tests", function() {
// console.log(resp);
done()
}).catch(err => {
throw err;
done(err);
})
})
it('Extract .mp4 to .flac', function (done) {
@@ -43,7 +44,7 @@ describe("Unit Tests", function() {
// console.log(resp);
done()
}).catch(err => {
throw err;
done(err);
})
})
it('Extracting to a nonexistant format', function (done) {
@@ -86,7 +87,7 @@ describe("Unit Tests", function() {
transcriptPath = resp
done()
}).catch(err => {
throw err
done(err)
})
})
@@ -111,7 +112,7 @@ describe("Unit Tests", function() {
mapFunctions.get("summarize-transcription").function(transcriptPath).then(resp => {
done()
}).catch(err => {
throw err
done(err)
})
})
@@ -128,7 +129,7 @@ describe("Unit Tests", function() {
summarizePath = resp
done()
}).catch(err => {
throw err
done(err)
})
})
@@ -145,20 +146,92 @@ describe("Unit Tests", function() {
this.slow(30000)
this.timeout(120000)
// it("ChatGPT", function (done){
// mapFunctions.get("chatgpt").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
// done()
// }).catch(err => {
// throw err
// })
// })
it("Gemini", function (done){
mapFunctions.get("llm-gemini").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
it("ChatGPT", function (done){
mapFunctions.get("llm-saia_openai_gpt").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/followup_report.txt", language: "en"}).then(resp => {
llmpath = resp
done()
}).catch(err => {
throw err
done(err)
})
})
it("Gemini", function (done){
mapFunctions.get("llm-gemini").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/followup_report.txt", language: "en"}).then(resp => {
done()
}).catch(err => {
if(err.includes("(503)")){done()} // Error 503 is gemini overload, so an Error that they can at any time throw at us which would crash the pipeline, so we just ignore it and we just imagine that the test passed
else{
console.log(err);
done(err)
}
})
})
it("Qwen3", function (done){
mapFunctions.get("qwen3-235b-a22b").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/followup_report.txt", language: "en"}).then(resp => {
done()
}).catch(err => {
done(err)
})
})
it("ChatGPT (Nonexistant Type File)", function (done){
mapFunctions.get("llm-saia_openai_gpt").function({inputTranscriptPath: summarizePath, documentTypePath: "a", language: "en"}).then(resp => {
done("Didnt crash")
}).catch(err => {
done()
})
})
it("Gemini (Nonexistant Type File)", function (done){
mapFunctions.get("llm-gemini").function({inputTranscriptPath: summarizePath, documentTypePath: "a", language: "en"}).then(resp => {
done("Didnt crash")
}).catch(err => {
done()
})
})
it("Qwen3 (Nonexistant Type File)", function (done){
mapFunctions.get("qwen3-235b-a22b").function({inputTranscriptPath: summarizePath, documentTypePath: "a", language: "en"}).then(resp => {
done("Didnt crash")
}).catch(err => {
done()
})
})
})
describe("Audio Snippet", function() {
this.slow(1000)
this.timeout(5000)
// transcriptPath = "A:\\programing\\@projects\\video2document\\storage\\transcriptionSummaries\\testvideo-1765900665001.json"
// audiopath = "A:\\programing\\@projects\\video2document\\storage\\audio\\testvideo.mp3"
it("Audio Snipper Generator", function (done){
mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: summarizePath }).then(resp => {
speakers = resp
done()
}).catch(err => {
done(err)
})
})
it("Audio Snipper Generator (Nonexistant Transcript File)", function (done){
mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: "a" }).then(resp => {
speakers = resp
done("Didnt crash")
}).catch(err => {
done()
})
})
it("Audio Snipper Generator (Nonexistant Audio File)", function (done){
mapFunctions.get("extract-speaker-snippets").function({audioPath: "a", jsonPath: summarizePath }).then(resp => {
speakers = resp
done("Didnt crash")
}).catch(err => {
done()
})
})
})