From 7494e13c8cd11d8c19071c8d56b0b417504bf79b Mon Sep 17 00:00:00 2001 From: "eric.minning" Date: Mon, 15 Dec 2025 17:01:04 +0100 Subject: [PATCH 1/7] Fixed an a wrong call of the speakerAudios function. --- electron/main/renderer.js | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/electron/main/renderer.js b/electron/main/renderer.js index 6ce2b29..f972d78 100644 --- a/electron/main/renderer.js +++ b/electron/main/renderer.js @@ -33,7 +33,6 @@ uploadContainer.addEventListener("drop", (e) => { window.addEventListener('load', async (e) => { try { - console.log("test"); loadLanguageOptions(); const value = await window.onStartup.getModuleNames(); loadAiOptions(value.ai_modules); @@ -117,7 +116,7 @@ docFormat.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); docFormatSummary1.addEventListener("change", (e) =>{ try { if(docFormatSummary1.checked){ @@ -129,7 +128,7 @@ docFormatSummary1.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); docFormatSummary2.addEventListener("change", (e) =>{ try { if(docFormatSummary2.checked){ @@ -141,7 +140,7 @@ docFormatSummary2.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); docFormatSummary3.addEventListener("change", (e) =>{ try { if(docFormatSummary3.checked){ @@ -153,7 +152,7 @@ docFormatSummary3.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); docFormatCustom.addEventListener("change", (e) =>{ try { if(docFormatCustom.checked){ @@ -165,7 +164,7 @@ docFormatCustom.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); //Speaker change listener cur_speaker.addEventListener("change", (e) =>{ @@ -174,16 +173,12 @@ cur_speaker.addEventListener("change", (e) =>{ } catch (error) { } -}) +}); -window.electron.speakerAudios((event, arg) => { - try { +window.audios.speakerAudios((event, arg) => { setSpeakerAudiosValue(arg); loadSpeakerOptions(arg); - } catch (error) { - - } -}) +}); window.electron.progress((event, arg) => { if(arg.curstep == 1){ @@ -207,7 +202,7 @@ function setCircleOne(){ } catch (error) { } -} +}; function setCircleZwo(){ try { if(document.getElementById("box2").style.backgroundColor == "green"){ @@ -219,7 +214,7 @@ function setCircleZwo(){ } -} +}; function setCircleThree(){ try { if(document.getElementById("box3").style.backgroundColor == "green"){ @@ -231,7 +226,7 @@ function setCircleThree(){ } -} +}; function setCircleFour(){ try { if(document.getElementById("box4").style.backgroundColor == "green"){ @@ -242,7 +237,7 @@ function setCircleFour(){ } catch (error) { } -} +}; From aee1428cb6e66a6c091df5046dc19e6a76541485 Mon Sep 17 00:00:00 2001 From: "eric.minning" Date: Mon, 15 Dec 2025 17:07:07 +0100 Subject: [PATCH 2/7] Changed location of the output type value in the response package --- electron/main/script.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/electron/main/script.js b/electron/main/script.js index 1ef9078..c1b6f19 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -49,15 +49,15 @@ function checkBoxes() { const sendingPackage = { "video": { "module":"extraction-video-to-audio", - "inputVideoPath": pathTest, - "outputType": outputType.value + "inputVideoPath": pathTest }, "transcription": { "module": transcriptionType.value }, "document": { "module":aiType.value, - "styles": selectedStyles + "styles": selectedStyles, + "outputType": outputType.value } }; window.submit.submit(sendingPackage) From bac6e2b7f05d6bb157ec1d02783a79f3dd3c9497 Mon Sep 17 00:00:00 2001 From: "eric.minning" Date: Mon, 15 Dec 2025 17:21:02 +0100 Subject: [PATCH 3/7] Implemented the function for the download button. --- electron/main/index.html | 7 +------ electron/main/preload.js | 5 +++++ electron/main/script.js | 8 +++++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/electron/main/index.html b/electron/main/index.html index 76ea47a..27b6137 100644 --- a/electron/main/index.html +++ b/electron/main/index.html @@ -147,12 +147,7 @@ diff --git a/electron/main/preload.js b/electron/main/preload.js index 4219f15..26aa314 100644 --- a/electron/main/preload.js +++ b/electron/main/preload.js @@ -25,6 +25,11 @@ try { contextBridge.exposeInMainWorld("submitSpeaker", { submitSpeaker: (speaker_names) => {ipcRenderer.send("speaker_submit", speaker_names)} }) + + contextBridge.exposeInMainWorld("download", { + file_download: () => {ipcRenderer.send("file_download")} + }) + ipcRenderer.on("error", (event, err) => {alert(err)}) } catch (error) { diff --git a/electron/main/script.js b/electron/main/script.js index c1b6f19..12b4f19 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -105,7 +105,6 @@ function changeLanguage(language) { function handleFiles(files) { try { if (files.length > 0) { - document.getElementById("progressbar").style.visibility = "visible"; const file = files[0]; if (file.type.startsWith('video/')) { const filePath = window.explorer.onFileDrop(files[0]) @@ -330,3 +329,10 @@ function sendSpeakerPackages(){ } } +function fileDownload(){ + try { + window.file_download.fileDownload(); + } catch (error) { + + } +} From 04b2457ca37bf21cc1c348869a7f8d9168e48b92 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Mon, 15 Dec 2025 17:58:03 +0100 Subject: [PATCH 4/7] Changes to the LLMs to return a Promise (outp path) and main now calls the export process --- main.js | 11 ++- services/modules/llm-chat_gpt/chatgpt.js | 115 ++++++++++++----------- services/modules/llm-gemini/gemini.js | 2 +- services/modules/quen3/quen3.js | 110 ++++++++++++---------- 4 files changed, 127 insertions(+), 111 deletions(-) diff --git a/main.js b/main.js index 6b9fe1c..1bc0bc7 100644 --- a/main.js +++ b/main.js @@ -124,10 +124,12 @@ electron.ipcMain.handle('get-module-names', async () => { // mainWindow.webContents.send("modules", module_array) // }) - +var globalArgs = {} +var globalFinalHtmlPath = "" electron.ipcMain.on("file_submit", async (event, args) => { try { + globalArgs = args let curstep = 0 let totalsteps = 3 + args.document.styles.length @@ -187,7 +189,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { await mapFunctions.get("module-handler").function(args.document.module, {inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/standard_meeting_report.txt", language: "en"}).then(resp => { console.log(resp); - transcriptpath = resp + globalFinalHtmlPath = resp curstep++ mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) }).catch(err => { @@ -195,7 +197,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { return }) } - + // TODO actually implement this functionality // Module to get the first few lines for each speaker to send to the frontend // await mapFunctions.get("speaker-getter-idfk").function(transcriptpath).then(resp => { @@ -220,6 +222,9 @@ electron.ipcMain.on("file_submit", async (event, args) => { } }) +electron.ipcMain.on("file_download", async() => { + await mapFunctions.get("htmlDocumentConverter").convert({inputPath:globalFinalHtmlPath, format: globalArgs.document.outputType, showDialog: true}); +}) let q = diff --git a/services/modules/llm-chat_gpt/chatgpt.js b/services/modules/llm-chat_gpt/chatgpt.js index d07a422..4b7c89b 100644 --- a/services/modules/llm-chat_gpt/chatgpt.js +++ b/services/modules/llm-chat_gpt/chatgpt.js @@ -1,7 +1,7 @@ const fs = require('fs'); const path = require('path'); -const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory +const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist @@ -9,8 +9,7 @@ if (!fs.existsSync(outputDir)) { // Ensure SAIA API key is set in environment variables: export SAIA_API_KEY="your_api_key_here" const SAIA_API_KEY = process.env.SAIA_API_KEY; // Ensure SAIA API key is set in environment variables - -const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; //URL for the REST call, used model and action +const SAIA_URL = "https://chat-ai.academiccloud.de/v1/chat/completions"; // URL for the REST call, used model and action const module_exports = { name: "llm-saia_openai_gpt", @@ -19,66 +18,72 @@ const module_exports = { description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform", async function(parameter) { - try { - console.log("SAIA OpenAI GPT module invoked with parameters:", parameter); + return new Promise(async (resolve, reject) => { + try { + // console.log("SAIA OpenAI GPT module invoked with parameters:", parameter); - await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language - parameter.inputTranscriptPath, // Path to input transcript file - parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user - parameter.language // Language for the document which is chosen in the front end by the user - ); + resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language + parameter.inputTranscriptPath, // Path to input transcript file + parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user + parameter.language // Language for the document which is chosen in the front end by the user + )); + + } catch (error) { + // console.error("Error in SAIA OpenAI GPT module:", error); + reject(error) + } + }) - } catch (error) { - console.error("Error in SAIA OpenAI GPT module:", error); - } }, createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English - try { - const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path - const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path - const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed + return new Promise(async(resolve, reject) => { + try { + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path + const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed - // --- REST CALL --- - const response = await fetch(SAIA_URL, { - method: "POST", - headers: { - "Authorization": `Bearer ${SAIA_API_KEY}`, - "Accept": "application/json", - "Content-Type": "application/json" - }, - body: JSON.stringify({ - model: "openai-gpt-oss-120b", - messages: [ - { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, - { role: "user", content: promptText } - ], - temperature: 0 - }) - }); + // --- REST CALL --- + const response = await fetch(SAIA_URL, { //safe model response in variable + method: "POST", + headers: { + "Authorization": `Bearer ${SAIA_API_KEY}`, + "Accept": "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify({ + model: "openai-gpt-oss-120b", + messages: [ + { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, + { role: "user", content: promptText } + ], + temperature: 0 + }) + }); - if (!response.ok) { //ok is true when a response was successful - const text = await response.text(); - throw new Error(`SAIA API error (${response.status}): ${text}`); + if (!response.ok) { //ok is true when a responce was successfull + const text = await response.text(); + throw new Error(`SAIA API error (${response.status}): ${text}`); + } + + const data = await response.json(); + + // Get generated text from response or default to empty string (if null) + // SAIA uses OpenAI-compatible structure: data.choices[x].message.content + const output = data.choices?.[0]?.message?.content || ""; + let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file + // console.log(inputTranscriptName); + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name + fs.writeFileSync(outPath, output, "utf8"); // Write output to file + + // console.log("Generated document written to:", outPath); + resolve(outPath) + + } catch (error) { + // console.error("Error generating SAIA content:", error); + reject(error) } - - const data = await response.json(); - - // Get generated text from response or default to empty string (if null) - // SAIA uses OpenAI-compatible structure: data.choices[x].message.content - const output = data.choices?.[0]?.message?.content || ""; - - let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file - console.log(inputTranscriptName); - - const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name - fs.writeFileSync(outPath, output, "utf8"); // Write output to file - - console.log("Generated document written to:", outPath); - - } catch (error) { - console.error("Error generating SAIA content:", error); - } + }) } }; diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index cff1026..beff750 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -71,7 +71,7 @@ const module_exports = { const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file // console.log(inputTranscriptName); - const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name fs.writeFileSync(outPath, output, "utf8"); // Write output to file // console.log("Generated document written to:", outPath); diff --git a/services/modules/quen3/quen3.js b/services/modules/quen3/quen3.js index fd93737..0bc913a 100644 --- a/services/modules/quen3/quen3.js +++ b/services/modules/quen3/quen3.js @@ -18,66 +18,72 @@ const module_exports = { description: "Generates documents using QWEN 3 235B via SAIA platform", async function(parameter) { - try { - console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter); + return new Promise(async (resolve, reject) => { + try { + // console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter); - await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language - parameter.inputTranscriptPath, // Path to input transcript file - parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user - parameter.language // Language for the document which is chosen in the front end by the user - ); + resolve(await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language + parameter.inputTranscriptPath, // Path to input transcript file + parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user + parameter.language // Language for the document which is chosen in the front end by the user + )); + + } catch (error) { + // console.error("Error in SAIA QWEN 3 235B module:", error); + reject(error) + } + }) - } catch (error) { - console.error("Error in SAIA QWEN 3 235B module:", error); - } }, createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English - try { - const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path - const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path - const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed + return new Promise(async(resolve, reject) => { + try { + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path + const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed - // --- REST CALL --- - const response = await fetch(SAIA_URL, { - method: "POST", - headers: { - "Authorization": `Bearer ${SAIA_API_KEY}`, - "Accept": "application/json", - "Content-Type": "application/json" - }, - body: JSON.stringify({ - model: "qwen3-235b-a22b", - messages: [ - { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, - { role: "user", content: promptText } - ], - temperature: 0 - }) - }); + // --- REST CALL --- + const response = await fetch(SAIA_URL, { //safe model response in variable + method: "POST", + headers: { + "Authorization": `Bearer ${SAIA_API_KEY}`, + "Accept": "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify({ + model: "qwen3-235b-a22b", + messages: [ + { role: "system", content: "You are a helpful assistant that generates HTML documents from transcripts. Output only valid HTML content without any preamble, explanations, or markdown formatting." }, + { role: "user", content: promptText } + ], + temperature: 0 + }) + }); - if (!response.ok) { // ok is true when a response was successful - const text = await response.text(); - throw new Error(`SAIA API error (${response.status}): ${text}`); + if (!response.ok) { //ok is true when a responce was successfull + const text = await response.text(); + throw new Error(`SAIA API error (${response.status}): ${text}`); + } + + const data = await response.json(); + + // Get generated text from response or default to empty string (if null) + // SAIA uses OpenAI-compatible structure: data.choices[x].message.content + const output = data.choices?.[0]?.message?.content || ""; + let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file + // console.log(inputTranscriptName); + const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name + fs.writeFileSync(outPath, output, "utf8"); // Write output to file + + // console.log("Generated document written to:", outPath); + resolve(outPath) + + } catch (error) { + // console.error("Error generating SAIA content:", error); + reject(error) } - - const data = await response.json(); - - // Get generated text from response or default to empty string (if null) - // SAIA uses OpenAI-compatible structure: data.choices[x].message.content - const output = data.choices?.[0]?.message?.content || ""; - - let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file - console.log(inputTranscriptName); - - const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name - fs.writeFileSync(outPath, output, "utf8"); // Write output to file - - console.log("Generated document written to:", outPath); - - } catch (error) { - console.error("Error generating SAIA content:", error); - } + }) } }; From bd47a194c7943a579797c3032100fbe79c2faec4 Mon Sep 17 00:00:00 2001 From: "eric.minning" Date: Mon, 15 Dec 2025 18:09:50 +0100 Subject: [PATCH 5/7] Removed a line which caused an error --- electron/main/script.js | 1 - 1 file changed, 1 deletion(-) diff --git a/electron/main/script.js b/electron/main/script.js index 12b4f19..d46d7b3 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -25,7 +25,6 @@ function checkBoxes() { var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]); var pathToLower = pathTest.toLowerCase(); if(testEndings.some(e => pathToLower.endsWith(e))){ - document.getElementById("progressbar").style.visibility = "visible"; //assembly of the json for the main const selectedStyles = [checkedCounter]; From 6aa62ed534f29149aa50e969934afedb53802a26 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Mon, 15 Dec 2025 18:41:14 +0100 Subject: [PATCH 6/7] Enable download button functionality and improve error handling in file download --- electron/main/index.html | 3 +-- electron/main/script.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/electron/main/index.html b/electron/main/index.html index 27b6137..11cab72 100644 --- a/electron/main/index.html +++ b/electron/main/index.html @@ -147,8 +147,7 @@ + diff --git a/electron/main/script.js b/electron/main/script.js index d46d7b3..6500dbc 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -328,10 +328,10 @@ function sendSpeakerPackages(){ } } -function fileDownload(){ +function fileDownload() { try { - window.file_download.fileDownload(); + window.download.file_download(); } catch (error) { - + console.error("Download failed:", error); } } From 1b76b2e96d5a7c092aa73a98ef91ec0e3ed5bc9c Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Mon, 15 Dec 2025 18:47:41 +0100 Subject: [PATCH 7/7] oopsies missed a --- electron/main/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/electron/main/index.html b/electron/main/index.html index 11cab72..afb9797 100644 --- a/electron/main/index.html +++ b/electron/main/index.html @@ -148,6 +148,7 @@