Compare commits

...

12 Commits

Author SHA1 Message Date
MikeHughes-BIN 1b76b2e96d oopsies missed a </div> 2025-12-15 18:47:41 +01:00
MikeHughes-BIN 6aa62ed534 Enable download button functionality and improve error handling in file download 2025-12-15 18:41:14 +01:00
Hughes, Mike cd474d7101 Merge branch 'feature/ui-test' into 'develop'
Removed a line which caused an error

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

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

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

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

See merge request proj-wise2526-video2document/video2document!48
2025-12-15 17:09:06 +01:00
eric.minning aee1428cb6 Changed location of the output type value in the response package 2025-12-15 17:07:07 +01:00
eric.minning 7494e13c8c Fixed an a wrong call of the speakerAudios function. 2025-12-15 17:01:04 +01:00
8 changed files with 155 additions and 139 deletions
+1 -6
View File
@@ -147,12 +147,7 @@
</div>
<div class="step" id="step6" style="display:none;">
<button class="download-btn" id="downloadButton" onclick="" disabled>Download</button>
<div class="progressbar" id="progressbar">
<div class="progress_fill"></div>
<span class="progress_text">0%</span>
</div>
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button>
</div>
</div>
+5
View File
@@ -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) {
+12 -17
View File
@@ -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) {
}
}
};
+10 -5
View File
@@ -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];
@@ -49,15 +48,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)
@@ -105,7 +104,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 +328,10 @@ function sendSpeakerPackages(){
}
}
function fileDownload() {
try {
window.download.file_download();
} catch (error) {
console.error("Download failed:", error);
}
}
+8 -3
View File
@@ -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 =
+60 -55
View File
@@ -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);
}
})
}
};
+1 -1
View File
@@ -71,7 +71,7 @@ const module_exports = {
const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || "";
let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file
// console.log(inputTranscriptName);
const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name
const outPath = path.join(outputDir, `${inputTranscriptName}.html`); // Output file path & name to make naming dynamic. Pulled from input transcript name
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
// console.log("Generated document written to:", outPath);
+58 -52
View File
@@ -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);
}
})
}
};