Merge branch 'develop' into 'feature/35-backend-llm-chat-gpt-integration-s4-10'

# Conflicts:
#   services/modules/llm-gemini/gemini.js
This commit is contained in:
Hughes, Mike
2025-12-15 14:07:32 +01:00
20 changed files with 829 additions and 160 deletions
+16 -2
View File
@@ -963,9 +963,23 @@ app.*.symbols
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock !/dev/ci/**/Gemfile.lock
#Storage files # Storage files
storage/ storage/documents/*
storage/transcriptionSummaries/*
storage/transcripts/*
storage/video/*
# The inverse for the .gitkeep files, to make sure the folders are there but not the local files
!storage/documents/.gitkeep
!storage/transcriptionSummaries/.gitkeep
!storage/transcripts/.gitkeep
!storage/video/.gitkeep
*.mp4 *.mp4
*.webm
*.mp3
*.mov
*.wav *.wav
*.flac *.flac
!testvideo.mp4
+19 -25
View File
@@ -1,33 +1,27 @@
workflow: image: node:latest
rules:
# Run the pipeline for merge requests or when committing to a branch
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
image: python:3.14.0
stages: stages:
- setup # - install
- test - test
setup_environment: # job-install:
stage: setup # stage: install
script: # script:
- pip install --upgrade pip # - npm install
- pip install -r requirements.txt # artifacts:
- echo "Dependencies installed successfully." # untracked: false
# when: on_success
# access: all
# expire_in: "30 days"
# paths:
# - node_modules
only:
- main
- feature/ci-pipeline-s1-09a-1 # You can add more branches if needed
test_app:
job-test:
stage: test stage: test
script: script:
- echo "Running V2D Framework basic test..." - npm install
- python -m unittest discover || echo "No tests found." - echo "ASSEMBLYAI_API_KEY=$apikey_assembly" > .env
- echo "GOOGLE_API_KEY=$apikey_gemini" >> .env
only: - npm test
- main
- feature/ci-pipeline-s1-09a-1
+22 -2
View File
@@ -141,7 +141,7 @@ electron.ipcMain.on("file_submit", async (event, args) => {
console.log("\n\n Running the Video to Audio Extractor"); console.log("\n\n Running the Video to Audio Extractor");
// This code handles the Video to Audio extraction module call // This code handles the Video to Audio extraction module call
await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { 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); console.log(resp);
audiopath = resp audiopath = resp
curstep++ curstep++
@@ -183,7 +183,9 @@ electron.ipcMain.on("file_submit", async (event, args) => {
// TODO implement documentation module // TODO implement documentation module
// This code handles the Text to Document processing module call // This code handles the Text to Document processing module call
for (let i = 0; i < args.document.styles.length; i++) { for (let i = 0; i < args.document.styles.length; i++) {
await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { 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/meetingReport.json", language: "en"}).then(resp => {
console.log(resp); console.log(resp);
transcriptpath = resp transcriptpath = resp
curstep++ curstep++
@@ -194,6 +196,24 @@ electron.ipcMain.on("file_submit", async (event, args) => {
}) })
} }
// TODO actually implement this functionality
// Module to get the first few lines for each speaker to send to the frontend
// await mapFunctions.get("speaker-getter-idfk").function(transcriptpath).then(resp => {
// console.log(resp);
// transcriptpath = resp
// curstep++
// mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
// // {
// // speakerA: {source: "Pfad zur Audio File"},
// // speakerB:.....
// // }
mainWindow.webContents.send("speakers", {speakerA:"pfad1", speakerB:"pfad2"})
// }).catch(err => {
// mainWindow.webContents.send("error", err)
// return
// })
} catch (error) { } catch (error) {
console.log(error); console.log(error);
+456 -12
View File
@@ -12,12 +12,12 @@
"@google/genai": "^1.30.0", "@google/genai": "^1.30.0",
"@types/axios": "^0.9.36", "@types/axios": "^0.9.36",
"axios": "^1.13.2", "axios": "^1.13.2",
"cli-progress": "^3.12.0",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"electron": "^39.1.1", "electron": "^39.1.1",
"express": "^5.1.0", "express": "^5.1.0",
"ffmpeg-static": "^5.2.0", "ffmpeg-static": "^5.2.0",
"fluent-ffmpeg": "^2.1.3" "fluent-ffmpeg": "^2.1.3",
"mocha": "^11.7.5"
}, },
"devDependencies": { "devDependencies": {
"@types/cli-progress": "^3.11.6", "@types/cli-progress": "^3.11.6",
@@ -299,7 +299,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz",
"integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
@@ -398,6 +397,11 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/async": { "node_modules/async": {
"version": "0.2.10", "version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
@@ -489,6 +493,11 @@
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
} }
}, },
"node_modules/browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
},
"node_modules/buffer-crc32": { "node_modules/buffer-crc32": {
"version": "0.2.13", "version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@@ -568,22 +577,118 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/caseless": { "node_modules/caseless": {
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/cli-progress": { "node_modules/chalk": {
"version": "3.12.0", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"license": "MIT",
"dependencies": { "dependencies": {
"string-width": "^4.2.3" "ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}, },
"engines": { "engines": {
"node": ">=4" "node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chalk/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/chalk/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/cliui/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/cliui/node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
} }
}, },
"node_modules/clone-response": { "node_modules/clone-response": {
@@ -733,6 +838,17 @@
} }
} }
}, },
"node_modules/decamelize": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/decompress-response": { "node_modules/decompress-response": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -982,6 +1098,14 @@
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"optional": true "optional": true
}, },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"engines": {
"node": ">=6"
}
},
"node_modules/escape-html": { "node_modules/escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -991,7 +1115,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"optional": true,
"engines": { "engines": {
"node": ">=10" "node": ">=10"
}, },
@@ -1134,6 +1257,29 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"bin": {
"flat": "cli.js"
}
},
"node_modules/fluent-ffmpeg": { "node_modules/fluent-ffmpeg": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz",
@@ -1310,6 +1456,14 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -1500,6 +1654,14 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/has-property-descriptors": { "node_modules/has-property-descriptors": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
@@ -1548,6 +1710,14 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"bin": {
"he": "bin/he"
}
},
"node_modules/http-cache-semantics": { "node_modules/http-cache-semantics": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
@@ -1655,11 +1825,38 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-promise": { "node_modules/is-promise": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
}, },
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isexe": { "node_modules/isexe": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -1680,6 +1877,17 @@
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
} }
}, },
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-bigint": { "node_modules/json-bigint": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
@@ -1735,6 +1943,35 @@
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
}, },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dependencies": {
"p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dependencies": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lowercase-keys": { "node_modules/lowercase-keys": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
@@ -1843,6 +2080,49 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/mocha": {
"version": "11.7.5",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz",
"integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==",
"dependencies": {
"browser-stdout": "^1.3.1",
"chokidar": "^4.0.1",
"debug": "^4.3.5",
"diff": "^7.0.0",
"escape-string-regexp": "^4.0.0",
"find-up": "^5.0.0",
"glob": "^10.4.5",
"he": "^1.2.0",
"is-path-inside": "^3.0.3",
"js-yaml": "^4.1.0",
"log-symbols": "^4.1.0",
"minimatch": "^9.0.5",
"ms": "^2.1.3",
"picocolors": "^1.1.1",
"serialize-javascript": "^6.0.2",
"strip-json-comments": "^3.1.1",
"supports-color": "^8.1.1",
"workerpool": "^9.2.0",
"yargs": "^17.7.2",
"yargs-parser": "^21.1.1",
"yargs-unparser": "^2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
"mocha": "bin/mocha.js"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/mocha/node_modules/diff": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
"integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -1951,6 +2231,34 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dependencies": {
"p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/package-json-from-dist": { "node_modules/package-json-from-dist": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -1969,6 +2277,14 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"engines": {
"node": ">=8"
}
},
"node_modules/path-key": { "node_modules/path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -2006,6 +2322,11 @@
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
}, },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/progress": { "node_modules/progress": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -2066,6 +2387,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/range-parser": { "node_modules/range-parser": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -2102,6 +2431,26 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/resolve-alpn": { "node_modules/resolve-alpn": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
@@ -2239,6 +2588,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
@@ -2431,6 +2788,17 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sumchecker": { "node_modules/sumchecker": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
@@ -2442,6 +2810,20 @@
"node": ">= 8.0" "node": ">= 8.0"
} }
}, },
"node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/toidentifier": { "node_modules/toidentifier": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -2531,7 +2913,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -2603,6 +2984,11 @@
"which": "bin/which" "which": "bin/which"
} }
}, },
"node_modules/workerpool": {
"version": "9.3.4",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz",
"integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg=="
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
@@ -2721,6 +3107,53 @@
} }
} }
}, },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/yargs-unparser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dependencies": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
"flat": "^5.0.2",
"is-plain-obj": "^2.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yauzl": { "node_modules/yauzl": {
"version": "2.10.0", "version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
@@ -2739,6 +3172,17 @@
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
} }
} }
} }
+3 -3
View File
@@ -3,12 +3,12 @@
"@google/genai": "^1.30.0", "@google/genai": "^1.30.0",
"@types/axios": "^0.9.36", "@types/axios": "^0.9.36",
"axios": "^1.13.2", "axios": "^1.13.2",
"cli-progress": "^3.12.0",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"electron": "^39.1.1", "electron": "^39.1.1",
"express": "^5.1.0", "express": "^5.1.0",
"ffmpeg-static": "^5.2.0", "ffmpeg-static": "^5.2.0",
"fluent-ffmpeg": "^2.1.3" "fluent-ffmpeg": "^2.1.3",
"mocha": "^11.7.5"
}, },
"devDependencies": { "devDependencies": {
"@types/cli-progress": "^3.11.6", "@types/cli-progress": "^3.11.6",
@@ -27,7 +27,7 @@
}, },
"scripts": { "scripts": {
"start": "electron main.js", "start": "electron main.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "mocha ./test/unit/test.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
-3
View File
@@ -1,3 +0,0 @@
fastapi
uvicorn
pytest
+1 -1
View File
@@ -11,7 +11,7 @@ config = require("./config/config")
ffmpegPath = require('ffmpeg-static'); ffmpegPath = require('ffmpeg-static');
ffmpeg = require('fluent-ffmpeg'); ffmpeg = require('fluent-ffmpeg');
path = require('path'); path = require('path');
cliProgress = require('cli-progress'); // cliProgress = require('cli-progress');
// { app, BrowserWindow, ipcMain, dialog } = require('electron'); // { app, BrowserWindow, ipcMain, dialog } = require('electron');
+5 -22
View File
@@ -24,17 +24,11 @@ module.exports = {
outputType: String // Audio file output format outputType: String // Audio file output format
} }
*/ */
let progressBar = new cliProgress.SingleBar({
format: 'Processing |{bar}| {percentage}% | {timemark}',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true
});
try { try {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.extractAudioFromVideo(parameter.inputVideoPath, progressBar, parameter.outputType) this.extractAudioFromVideo(parameter.inputVideoPath, parameter.outputType)
.then((resp) => resolve(resp)) .then((resp) => resolve(resp))
.catch((err) => console.error(err)); .catch((err) => {reject(err)});
}) })
} catch (error) { } catch (error) {
console.log(parameter.outputType); console.log(parameter.outputType);
@@ -52,7 +46,7 @@ module.exports = {
* - Shows CLI progress bar * - Shows CLI progress bar
* - Handles errors gracefully (without errors) * - Handles errors gracefully (without errors)
*/ */
extractAudioFromVideo: async function (videoFilePath, progressBar, outputType){ extractAudioFromVideo: async function (videoFilePath, outputType){
let inputVideoName = path.basename(videoFilePath, path.extname(videoFilePath)); let inputVideoName = path.basename(videoFilePath, path.extname(videoFilePath));
let outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`); let outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`);
@@ -63,28 +57,17 @@ module.exports = {
// .audioCodec('pcm_s16le') // .audioCodec('pcm_s16le')
.audioChannels(1) .audioChannels(1)
.audioFrequency(16000) .audioFrequency(16000)
// .setFfmpegPath("./ffmpeg.exe")
.on('progress', (progress) => {
if (!progressBar.isActive) progressBar.start(100, 0, { timemark: '00:00:00' });
if (progress.percent) {
progressBar.update(progress.percent, { timemark: progress.timemark });
}
})
.on('end', () => { .on('end', () => {
progressBar.update(100, { timemark: 'done' });
progressBar.stop();
console.log(`Extraction completed: ${outputAudioPath}`);
resolve(outputAudioPath); resolve(outputAudioPath);
}) })
.on('error', (err) => { .on('error', (err) => {
progressBar.stop(); // console.error(`failed_audio_extraction on type ${outputType}: ${err.message}`);
console.error(`failed_audio_extraction on type ${outputType}: ${err.message}`);
reject(err); reject(err);
}) })
.save(outputAudioPath); .save(outputAudioPath);
} catch (error) { } catch (error) {
console.log(); // console.log(error);
} }
}); });
} }
@@ -21,30 +21,36 @@ module.exports = {
const raw = fs.readFileSync(args.jsonPath, "utf-8"); const raw = fs.readFileSync(args.jsonPath, "utf-8");
inputJson = JSON.parse(raw); inputJson = JSON.parse(raw);
} catch (e) { } catch (e) {
console.error("Failed to load JSON from file:", e); // console.error("Failed to load JSON from file:", e);
return { error: "Could not read JSON from file path." }; reject(e)
return
} }
} }
// JSON parsen // JSON parsen
if (typeof args === "string") { if (typeof args === "string") {
try { try {
await new Promise((res) => { await new Promise((res, rej) => {
fs.readFile(args, 'utf8', function (err, data) { fs.readFile(args, 'utf8', function (err, data) {
if (err) throw err; if (err){
rej(err)
return
}
inputJson = JSON.parse(data); inputJson = JSON.parse(data);
res() res()
}); });
}) })
} catch (e) { } catch (e) {
console.log("Invalid JSON in summarize-transcription"); // console.log("Invalid JSON in summarize-transcription");
console.log(e) // console.log(e)
return { error: "Invalid JSON" }; reject(e)
return
} }
} }
const words = inputJson.words; const words = inputJson.words;
if (!Array.isArray(words)) { if (!Array.isArray(words)) {
return { error: "No words Array found" }; reject("No words Array found")
return
} }
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
@@ -136,11 +142,11 @@ module.exports = {
const txtPath = path.join(outputDir, "transcription_result.txt"); const txtPath = path.join(outputDir, "transcription_result.txt");
fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); // console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
resolve(jsonPath); resolve(jsonPath);
} catch (err) { } catch (err) {
console.error("Error saving Summary:", err); // console.error("Error saving Summary:", err);
reject(err); reject(err);
} }
}) })
@@ -32,29 +32,35 @@ module.exports = {
inputJson = JSON.parse(raw); inputJson = JSON.parse(raw);
} catch (e) { } catch (e) {
console.error("Failed to load JSON from file:", e); console.error("Failed to load JSON from file:", e);
return { error: "Could not read JSON from file path." }; reject("Could not read JSON from file path.")
return
} }
} }
// JSON parsen // JSON parsen
if (typeof args === "string") { if (typeof args === "string") {
try { try {
await new Promise((res) => { await new Promise((res, rej) => {
fs.readFile(args, 'utf8', function (err, data) { fs.readFile(args, 'utf8', function (err, data) {
if (err) throw err; if (err){
rej(err)
return
}
inputJson = JSON.parse(data); inputJson = JSON.parse(data);
res() res()
}); });
}) })
} catch (e) { } catch (e) {
console.log("Invalid JSON in summarize-transcription"); // console.log("Invalid JSON in summarize-transcription");
console.log(e) // console.log(e)
return { error: "Invalid JSON" }; reject(e)
return
} }
} }
const words = inputJson.words; const words = inputJson.words;
if (!Array.isArray(words)) { if (!Array.isArray(words)) {
return { error: "No words Array found" }; reject("No words Array found")
return;
} }
const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ?
@@ -132,10 +138,10 @@ module.exports = {
const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`); const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`);
fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); fs.writeFileSync(txtPath, output.join("\n"), "utf-8");
console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); // console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`);
resolve(jsonPath); resolve(jsonPath);
} catch (err) { } catch (err) {
console.error("Error saving Summary:", err); // console.error("Error saving Summary:", err);
reject(err); reject(err);
} }
}) })
+20 -15
View File
@@ -18,31 +18,33 @@ const module_exports = {
description: "Generates documents using Google Gemini LLM", description: "Generates documents using Google Gemini LLM",
async function(parameter) { async function(parameter) {
return new Promise(async (resolve, reject) => {
try { try {
console.log("Gemini LLM module invoked with parameters:", parameter); // console.log("Gemini LLM module invoked with parameters:", parameter);
await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language
parameter.inputTranscriptPath, // Path to input transcript file parameter.inputTranscriptPath, // Path to input transcript file
parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user
parameter.language // Language for the document which is chosen in the front end by the user parameter.language // Language for the document which is chosen in the front end by the user
); ));
} catch (error) { } catch (error) {
console.error("Error in Gemini LLM module:", error); // console.error("Error in Gemini LLM module:", error);
reject(error)
} }
})
}, },
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
return new Promise(async(resolve, reject) => {
try { try {
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
// Add system instruction for HTML output
const systemInstruction = "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting.";
const promptText = `${systemInstruction}\n\n${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed
// --- REST CALL --- // --- REST CALL ---
const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { // safe model response in variable const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json"
@@ -68,15 +70,18 @@ const module_exports = {
// Get generated text from response or default to empty string (if null) // Get generated text from response or default to empty string (if null)
const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
console.log(inputTranscriptName); // console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file fs.writeFileSync(outPath, output, "utf8"); // Write output to file
console.log("Generated document written to:", outPath); // console.log("Generated document written to:", outPath);
resolve(outPath)
} catch (error) { } catch (error) {
console.error("Error generating Gemini content:", error); // console.error("Error generating Gemini content:", error);
reject(error)
} }
})
} }
}; };
@@ -78,7 +78,7 @@ function saveTranscript(transcript, sessionId) {
const outputPath = path.join(outputDir, `${sessionId}.json`); const outputPath = path.join(outputDir, `${sessionId}.json`);
fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2)); fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2));
console.log(`Transcript saved: ${outputPath}`); // console.log(`Transcript saved: ${outputPath}`);
return outputPath; return outputPath;
} }
@@ -89,6 +89,7 @@ module.exports = {
name: 'assembly', name: 'assembly',
type: 'transcription', type: 'transcription',
displayname: 'AssemblyAI', displayname: 'AssemblyAI',
audioformat: "mp3",
async function(audioFileName) { async function(audioFileName) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
@@ -115,8 +116,9 @@ module.exports = {
resolve(saveTranscript(transcript, sessionId)); resolve(saveTranscript(transcript, sessionId));
} catch (error) { } catch (error) {
console.error('Transcription error:', error.message); // console.error('Transcription error:', error.message);
reject(error); reject(error);
return
} }
}) })
} }
+1
View File
@@ -1,3 +1,4 @@
module.exports = { module.exports = {
name:"Startup_function", name:"Startup_function",
async function(){ async function(){
+35
View File
@@ -0,0 +1,35 @@
{
"FORMAT": "markdown",
"GOAL":"Generate a structured meeting report (Markdown). **Output ONLY:** final .md. No meta.",
"STRUCTURE": {
"titlepage": ["title","date","start","end","duration","location","host","participants"],
"toc": "[section](#anchor) — HH:MM:SS",
"section": {
"h2": "<topic> — HH:MM:SS",
"summary": "1 sentence",
"key_points": "<=5 bullets, quotes optional",
"decisions": "list: text | owner | due",
"actions": "table: id | task | owner | due | status"
},
"exec_summary": "3 short sentences",
"consolidated": ["decisions", "actions"],
"appendix": "optional"
},
"STYLE": {
"tone": "neutral, concise",
"ts_format": "HH:MM:SS",
"no_meta": true
},
"PROCESS": {
"timestamps": "use if present; else estimate minimal",
"speakers": "use labels; else Speaker X",
"long_transcripts": "chunk → summarize → merge",
"unclear": "UNKLAR:<reason>"
},
"JSON_OUTPUT_OPTIONAL": true,
"PROMPT_SNIPPET": "Generate meeting report in markdown using STRUCTURE and STYLE. Output only the report."
}
-8
View File
@@ -1,8 +0,0 @@
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_health():
response = client.get("/health")
assert response.status_code == 200
+170
View File
@@ -0,0 +1,170 @@
// DO NOT TOUCH THIS
require("../../requires.js")
mapFunctions = new Map()
// Loading the Function Map
var path = `${mainDir}/services/modules`
var folders = fs.readdirSync(path).filter(function (file) {
return fs.statSync(path+'/'+file).isDirectory();
});
folders.forEach(element => {
var commandFiles = fs.readdirSync(`${path}/${element}`).filter(file => file.endsWith('.js') && !file.startsWith("index"));
for (const file of commandFiles) {
delete require.cache[require.resolve(`${path}/${element}/${file}`)];
const command = require(`${path}/${element}/${file}`);
mapFunctions.set(command.name, command);
}
});
// You can touch beyond this point
let audiopath
let transcriptPath
let summarizePath
let llmpath
describe("Unit Tests", function() {
describe('Audio Extraction', function () {
this.slow(1000)
this.timeout(3000)
it('Extract .mp4 to .mp3', function (done) {
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "mp3"}).then(resp => {
audiopath = resp
// console.log(resp);
done()
}).catch(err => {
throw err;
})
})
it('Extract .mp4 to .flac', function (done) {
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "flac"}).then(resp => {
// console.log(resp);
done()
}).catch(err => {
throw err;
})
})
it('Extracting to a nonexistant format', function (done) {
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: __dirname.replaceAll("\\","/")+"/testvideo.mp4", outputType: "qqq"}).then(resp => {
// console.log(resp);
done("Didnt crash")
}).catch(err => {
done()
})
})
it('Extracting from nonexistant file', function (done) {
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: "a", outputType: "mp3"}).then(resp => {
// console.log(resp);
done("Didnt crash")
}).catch(err => {
done()
})
})
it('Extracting from nonexistant file to nonexistant format', function (done) {
mapFunctions.get("extraction-video-to-audio").function({inputVideoPath: "a", outputType: "qqq"}).then(resp => {
// console.log(resp);
done("Didnt crash")
}).catch(err => {
done()
})
})
});
describe("Audio Transcription", function() {
this.slow(20000)
this.timeout(120000)
it('Assembly', function (done) {
mapFunctions.get("assembly").function(audiopath).then(resp => {
// console.log(resp);
transcriptPath = resp
done()
}).catch(err => {
throw err
})
})
it('Assembly Wrong file', function (done) {
mapFunctions.get("assembly").function("a").then(resp => {
// console.log(resp);
// transcriptPath = resp
done("Didnt crash")
}).catch(err => {
// console.log(err);
done()
})
})
// TODO add more Transcription Tool tests here
})
describe("Transcript Summarizer", function() {
this.slow(100)
this.timeout(1000)
it("Summarizer 1", function (done){
mapFunctions.get("summarize-transcription").function(transcriptPath).then(resp => {
done()
}).catch(err => {
throw err
})
})
it("Summarizer 1 Wrong File", function (done){
mapFunctions.get("summarize-transcription").function("a").then(resp => {
done("Didnt crash")
}).catch(err => {
done()
})
})
it("Summarizer 2 (Main)", function (done){
mapFunctions.get("summarize-transcription2").function(transcriptPath).then(resp => {
summarizePath = resp
done()
}).catch(err => {
throw err
})
})
it("Summarizer 2 (Main) Wrong File", function (done){
mapFunctions.get("summarize-transcription2").function("a").then(resp => {
done("Didnt crash")
}).catch(err => {
done()
})
})
})
describe("Large Language Model", function() {
this.slow(30000)
this.timeout(120000)
// it("ChatGPT", function (done){
// mapFunctions.get("chatgpt").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
// done()
// }).catch(err => {
// throw err
// })
// })
it("Gemini", function (done){
mapFunctions.get("llm-gemini").function({inputTranscriptPath: summarizePath, documentTypePath: "./storage/documentType/meetingReport.json", language: "en"}).then(resp => {
llmpath = resp
done()
}).catch(err => {
throw err
})
})
})
after(function() {
console.log(`\n\n\n${audiopath} \n${transcriptPath} \n${summarizePath} \n${llmpath}`);
})
})
Binary file not shown.