diff --git a/.gitignore b/.gitignore index 8bf7970..df81756 100644 --- a/.gitignore +++ b/.gitignore @@ -963,9 +963,23 @@ app.*.symbols !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages !/dev/ci/**/Gemfile.lock -#Storage files -storage/ +# Storage files +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 +*.webm +*.mp3 +*.mov *.wav *.flac + + +!testvideo.mp4 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5bebd17..31c1209 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,33 +1,27 @@ -workflow: - rules: - # Run the pipeline for merge requests or when committing to a branch - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -image: python:3.14.0 +image: node:latest stages: - - setup + # - install - test -setup_environment: - stage: setup - script: - - pip install --upgrade pip - - pip install -r requirements.txt - - echo "Dependencies installed successfully." +# job-install: +# stage: install +# script: +# - npm install +# artifacts: +# 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 script: - - echo "Running V2D Framework basic test..." - - python -m unittest discover || echo "No tests found." - - only: - - main - - feature/ci-pipeline-s1-09a-1 - + - npm install + - echo "ASSEMBLYAI_API_KEY=$apikey_assembly" > .env + - echo "GOOGLE_API_KEY=$apikey_gemini" >> .env + - npm test \ No newline at end of file diff --git a/main.js b/main.js index 39c408d..2e80d3e 100644 --- a/main.js +++ b/main.js @@ -141,7 +141,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { console.log("\n\n Running the Video to Audio Extractor"); // This code handles the Video to Audio extraction module call - await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: 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); audiopath = resp curstep++ @@ -183,7 +183,9 @@ electron.ipcMain.on("file_submit", async (event, args) => { // TODO implement documentation module // This code handles the Text to Document processing module call 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); transcriptpath = resp 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) { console.log(error); diff --git a/package-lock.json b/package-lock.json index bf45f52..372d473 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,12 @@ "@google/genai": "^1.30.0", "@types/axios": "^0.9.36", "axios": "^1.13.2", - "cli-progress": "^3.12.0", "dotenv": "^17.2.3", "electron": "^39.1.1", "express": "^5.1.0", "ffmpeg-static": "^5.2.0", - "fluent-ffmpeg": "^2.1.3" + "fluent-ffmpeg": "^2.1.3", + "mocha": "^11.7.5" }, "devDependencies": { "@types/cli-progress": "^3.11.6", @@ -299,7 +299,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" } @@ -398,6 +397,11 @@ "dev": true, "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": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -489,6 +493,11 @@ "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": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -568,22 +577,118 @@ "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": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "license": "Apache-2.0" }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "string-width": "^4.2.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "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": { @@ -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": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -982,6 +1098,14 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "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": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -991,7 +1115,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "optional": true, "engines": { "node": ">=10" }, @@ -1134,6 +1257,29 @@ "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": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", @@ -1310,6 +1456,14 @@ "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": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -1500,6 +1654,14 @@ "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": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -1548,6 +1710,14 @@ "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": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", @@ -1655,11 +1825,38 @@ "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": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "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": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1680,6 +1877,17 @@ "@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": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -1735,6 +1943,35 @@ "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": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -1843,6 +2080,49 @@ "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": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1951,6 +2231,34 @@ "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": { "version": "1.0.1", "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_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": { "version": "3.1.1", "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", "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": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2066,6 +2387,14 @@ "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": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2102,6 +2431,26 @@ "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": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -2239,6 +2588,14 @@ "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": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", @@ -2431,6 +2788,17 @@ "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": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -2442,6 +2810,20 @@ "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": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -2531,7 +2913,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2603,6 +2984,11 @@ "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": { "version": "8.1.0", "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": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -2739,6 +3172,17 @@ "engines": { "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" + } } } } diff --git a/package.json b/package.json index 4b6cc7b..bdb3fe0 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "@google/genai": "^1.30.0", "@types/axios": "^0.9.36", "axios": "^1.13.2", - "cli-progress": "^3.12.0", "dotenv": "^17.2.3", "electron": "^39.1.1", "express": "^5.1.0", "ffmpeg-static": "^5.2.0", - "fluent-ffmpeg": "^2.1.3" + "fluent-ffmpeg": "^2.1.3", + "mocha": "^11.7.5" }, "devDependencies": { "@types/cli-progress": "^3.11.6", @@ -27,7 +27,7 @@ }, "scripts": { "start": "electron main.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "mocha ./test/unit/test.js" }, "repository": { "type": "git", diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 36a15fc..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -fastapi -uvicorn -pytest diff --git a/requires.js b/requires.js index fa410f3..da3b9aa 100644 --- a/requires.js +++ b/requires.js @@ -11,7 +11,7 @@ config = require("./config/config") ffmpegPath = require('ffmpeg-static'); ffmpeg = require('fluent-ffmpeg'); path = require('path'); -cliProgress = require('cli-progress'); +// cliProgress = require('cli-progress'); // { app, BrowserWindow, ipcMain, dialog } = require('electron'); diff --git a/services/modules/extraction/ffmpegExtractor.js b/services/modules/extraction/ffmpegExtractor.js index 2f00b15..c91eacf 100644 --- a/services/modules/extraction/ffmpegExtractor.js +++ b/services/modules/extraction/ffmpegExtractor.js @@ -24,17 +24,11 @@ module.exports = { outputType: String // Audio file output format } */ - let progressBar = new cliProgress.SingleBar({ - format: 'Processing |{bar}| {percentage}% | {timemark}', - barCompleteChar: '\u2588', - barIncompleteChar: '\u2591', - hideCursor: true - }); try { return new Promise((resolve, reject) => { - this.extractAudioFromVideo(parameter.inputVideoPath, progressBar, parameter.outputType) + this.extractAudioFromVideo(parameter.inputVideoPath, parameter.outputType) .then((resp) => resolve(resp)) - .catch((err) => console.error(err)); + .catch((err) => {reject(err)}); }) } catch (error) { console.log(parameter.outputType); @@ -52,7 +46,7 @@ module.exports = { * - Shows CLI progress bar * - 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 outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`); @@ -63,28 +57,17 @@ module.exports = { // .audioCodec('pcm_s16le') .audioChannels(1) .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', () => { - progressBar.update(100, { timemark: 'done' }); - progressBar.stop(); - console.log(`Extraction completed: ${outputAudioPath}`); resolve(outputAudioPath); }) .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); }) .save(outputAudioPath); } catch (error) { - console.log(); + // console.log(error); } }); } diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index 745c5b7..1be34a3 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -21,30 +21,36 @@ module.exports = { const raw = fs.readFileSync(args.jsonPath, "utf-8"); inputJson = JSON.parse(raw); } catch (e) { - console.error("Failed to load JSON from file:", e); - return { error: "Could not read JSON from file path." }; + // console.error("Failed to load JSON from file:", e); + reject(e) + return } } // JSON parsen if (typeof args === "string") { try { - await new Promise((res) => { + await new Promise((res, rej) => { fs.readFile(args, 'utf8', function (err, data) { - if (err) throw err; + if (err){ + rej(err) + return + } inputJson = JSON.parse(data); res() }); }) } catch (e) { - console.log("Invalid JSON in summarize-transcription"); - console.log(e) - return { error: "Invalid JSON" }; + // console.log("Invalid JSON in summarize-transcription"); + // console.log(e) + reject(e) + return } } const words = inputJson.words; if (!Array.isArray(words)) { - return { error: "No words Array found" }; + reject("No words Array found") + return } const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? @@ -136,11 +142,11 @@ module.exports = { const txtPath = path.join(outputDir, "transcription_result.txt"); 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); } catch (err) { - console.error("Error saving Summary:", err); + // console.error("Error saving Summary:", err); reject(err); } }) diff --git a/services/modules/jsonTools/transcriptionSummarizer2.js b/services/modules/jsonTools/transcriptionSummarizer2.js index 60d0bb8..aefe70c 100644 --- a/services/modules/jsonTools/transcriptionSummarizer2.js +++ b/services/modules/jsonTools/transcriptionSummarizer2.js @@ -32,29 +32,35 @@ module.exports = { inputJson = JSON.parse(raw); } catch (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 - if (typeof args === "string") { - try { - await new Promise((res) => { - fs.readFile(args, 'utf8', function (err, data) { - if (err) throw err; - inputJson = JSON.parse(data); - res() - }); - }) - } catch (e) { - console.log("Invalid JSON in summarize-transcription"); - console.log(e) - return { error: "Invalid JSON" }; - } + if (typeof args === "string") { + try { + await new Promise((res, rej) => { + fs.readFile(args, 'utf8', function (err, data) { + if (err){ + rej(err) + return + } + inputJson = JSON.parse(data); + res() + }); + }) + } catch (e) { + // console.log("Invalid JSON in summarize-transcription"); + // console.log(e) + reject(e) + return } + } const words = inputJson.words; if (!Array.isArray(words)) { - return { error: "No words Array found" }; + reject("No words Array found") + return; } const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? @@ -70,7 +76,7 @@ module.exports = { if (!currentSpeaker) currentSpeaker = w.speaker; if (startTime === null) startTime = w.start; endTime = w.end; - + //speaker changing if (currentSpeaker !== w.speaker && currentSentence) { result.push({ @@ -132,10 +138,10 @@ module.exports = { const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`); 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); } catch (err) { - console.error("Error saving Summary:", err); + // console.error("Error saving Summary:", err); reject(err); } }) diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index 892560e..cff1026 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -18,65 +18,70 @@ const module_exports = { description: "Generates documents using Google Gemini LLM", async function(parameter) { - try { - console.log("Gemini LLM module invoked with parameters:", parameter); + return new Promise(async (resolve, reject) => { + try { + // console.log("Gemini LLM 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 Gemini LLM module:", error); + reject(error) + } + }) - } catch (error) { - console.error("Error in Gemini LLM module:", error); - } }, createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English - 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 - - // 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 + 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(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { // safe model response in variable - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - contents: [ - { - parts: [ - { text: promptText } // Input prompt for content generation - ] - } - ] - }) - }); + // --- REST CALL --- + const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + contents: [ + { + parts: [ + { text: promptText } // Input prompt for content generation + ] + } + ] + }) + }); - if (!response.ok) { //ok is true when a responce was successfull - const text = await response.text(); - throw new Error(`Gemini API error (${response.status}): ${text}`); + if (!response.ok) { //ok is true when a responce was successfull + const text = await response.text(); + throw new Error(`Gemini API error (${response.status}): ${text}`); + } + + const data = await response.json(); + + // Get generated text from response or default to empty string (if null) + const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; + let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file + // console.log(inputTranscriptName); + const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name + fs.writeFileSync(outPath, output, "utf8"); // Write output to file + + // console.log("Generated document written to:", outPath); + resolve(outPath) + + } catch (error) { + // console.error("Error generating Gemini content:", error); + reject(error) } - - const data = await response.json(); - - // Get generated text from response or default to empty string (if null) - const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; - let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file - console.log(inputTranscriptName); - const outPath = path.join(outputDir, `${inputTranscriptName}.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 Gemini content:", error); - } + }) } }; diff --git a/services/modules/transcription-remote/assembly.js b/services/modules/transcription-remote/assembly.js index 3b02e4c..442d290 100644 --- a/services/modules/transcription-remote/assembly.js +++ b/services/modules/transcription-remote/assembly.js @@ -78,7 +78,7 @@ function saveTranscript(transcript, sessionId) { const outputPath = path.join(outputDir, `${sessionId}.json`); fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2)); - console.log(`Transcript saved: ${outputPath}`); + // console.log(`Transcript saved: ${outputPath}`); return outputPath; } @@ -89,6 +89,7 @@ module.exports = { name: 'assembly', type: 'transcription', displayname: 'AssemblyAI', + audioformat: "mp3", async function(audioFileName) { return new Promise(async (resolve, reject) => { @@ -115,8 +116,9 @@ module.exports = { resolve(saveTranscript(transcript, sessionId)); } catch (error) { - console.error('Transcription error:', error.message); + // console.error('Transcription error:', error.message); reject(error); + return } }) } diff --git a/services/modules/utility/@startup.js b/services/modules/utility/@startup.js index cf6eaf8..64f0b20 100644 --- a/services/modules/utility/@startup.js +++ b/services/modules/utility/@startup.js @@ -1,3 +1,4 @@ + module.exports = { name:"Startup_function", async function(){ diff --git a/test/.gitkeep b/storage/documentType/.gitkeep similarity index 100% rename from test/.gitkeep rename to storage/documentType/.gitkeep diff --git a/storage/documentType/meetingReport.json b/storage/documentType/meetingReport.json new file mode 100644 index 0000000..35e22ff --- /dev/null +++ b/storage/documentType/meetingReport.json @@ -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": " — 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:" + }, + + "JSON_OUTPUT_OPTIONAL": true, + + "PROMPT_SNIPPET": "Generate meeting report in markdown using STRUCTURE and STYLE. Output only the report." +} \ No newline at end of file diff --git a/test/unit/.gitkeep b/storage/documents/.gitkeep similarity index 100% rename from test/unit/.gitkeep rename to storage/documents/.gitkeep diff --git a/storage/transcriptionSummaries/.gitkeep b/storage/transcriptionSummaries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/test_health.py b/test/test_health.py deleted file mode 100644 index 7b088a7..0000000 --- a/test/test_health.py +++ /dev/null @@ -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 diff --git a/test/unit/test.js b/test/unit/test.js new file mode 100644 index 0000000..3560969 --- /dev/null +++ b/test/unit/test.js @@ -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}`); + }) +}) + + diff --git a/test/unit/testvideo.mp4 b/test/unit/testvideo.mp4 new file mode 100644 index 0000000..625a31f Binary files /dev/null and b/test/unit/testvideo.mp4 differ