mirror of
https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
synced 2026-06-15 18:01:52 +02:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6cff6b9981 | |||
| 0003d99041 | |||
| 6a94f88e86 | |||
| 30f73f7bb7 | |||
| 74439d680e | |||
| 1b76b2e96d | |||
| 363ba2d1b5 | |||
| 6aa62ed534 | |||
| cd474d7101 | |||
| bd47a194c7 | |||
| ef080063a8 | |||
| c2c1aa1b17 | |||
| ee3bcdcd05 | |||
| 04b2457ca3 | |||
| bac6e2b7f0 | |||
| 9760704883 | |||
| aee1428cb6 | |||
| 7494e13c8c |
@@ -147,12 +147,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step" id="step6" style="display:none;">
|
<div class="step" id="step6" style="display:none;">
|
||||||
<button class="download-btn" id="downloadButton" onclick="" disabled>Download</button>
|
<button class="download-btn" id="downloadButton" onclick="fileDownload()">Download</button>
|
||||||
|
|
||||||
<div class="progressbar" id="progressbar">
|
|
||||||
<div class="progress_fill"></div>
|
|
||||||
<span class="progress_text">0%</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ try {
|
|||||||
contextBridge.exposeInMainWorld("submitSpeaker", {
|
contextBridge.exposeInMainWorld("submitSpeaker", {
|
||||||
submitSpeaker: (speaker_names) => {ipcRenderer.send("speaker_submit", speaker_names)}
|
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)})
|
ipcRenderer.on("error", (event, err) => {alert(err)})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
+12
-17
@@ -33,7 +33,6 @@ uploadContainer.addEventListener("drop", (e) => {
|
|||||||
|
|
||||||
window.addEventListener('load', async (e) => {
|
window.addEventListener('load', async (e) => {
|
||||||
try {
|
try {
|
||||||
console.log("test");
|
|
||||||
loadLanguageOptions();
|
loadLanguageOptions();
|
||||||
const value = await window.onStartup.getModuleNames();
|
const value = await window.onStartup.getModuleNames();
|
||||||
loadAiOptions(value.ai_modules);
|
loadAiOptions(value.ai_modules);
|
||||||
@@ -117,7 +116,7 @@ docFormat.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
docFormatSummary1.addEventListener("change", (e) =>{
|
docFormatSummary1.addEventListener("change", (e) =>{
|
||||||
try {
|
try {
|
||||||
if(docFormatSummary1.checked){
|
if(docFormatSummary1.checked){
|
||||||
@@ -129,7 +128,7 @@ docFormatSummary1.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
docFormatSummary2.addEventListener("change", (e) =>{
|
docFormatSummary2.addEventListener("change", (e) =>{
|
||||||
try {
|
try {
|
||||||
if(docFormatSummary2.checked){
|
if(docFormatSummary2.checked){
|
||||||
@@ -141,7 +140,7 @@ docFormatSummary2.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
docFormatSummary3.addEventListener("change", (e) =>{
|
docFormatSummary3.addEventListener("change", (e) =>{
|
||||||
try {
|
try {
|
||||||
if(docFormatSummary3.checked){
|
if(docFormatSummary3.checked){
|
||||||
@@ -153,7 +152,7 @@ docFormatSummary3.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
docFormatCustom.addEventListener("change", (e) =>{
|
docFormatCustom.addEventListener("change", (e) =>{
|
||||||
try {
|
try {
|
||||||
if(docFormatCustom.checked){
|
if(docFormatCustom.checked){
|
||||||
@@ -165,7 +164,7 @@ docFormatCustom.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
//Speaker change listener
|
//Speaker change listener
|
||||||
cur_speaker.addEventListener("change", (e) =>{
|
cur_speaker.addEventListener("change", (e) =>{
|
||||||
@@ -174,16 +173,12 @@ cur_speaker.addEventListener("change", (e) =>{
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
window.electron.speakerAudios((event, arg) => {
|
window.audios.speakerAudios((event, arg) => {
|
||||||
try {
|
|
||||||
setSpeakerAudiosValue(arg);
|
setSpeakerAudiosValue(arg);
|
||||||
loadSpeakerOptions(arg);
|
loadSpeakerOptions(arg);
|
||||||
} catch (error) {
|
});
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
window.electron.progress((event, arg) => {
|
window.electron.progress((event, arg) => {
|
||||||
if(arg.curstep == 1){
|
if(arg.curstep == 1){
|
||||||
@@ -207,7 +202,7 @@ function setCircleOne(){
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
};
|
||||||
function setCircleZwo(){
|
function setCircleZwo(){
|
||||||
try {
|
try {
|
||||||
if(document.getElementById("box2").style.backgroundColor == "green"){
|
if(document.getElementById("box2").style.backgroundColor == "green"){
|
||||||
@@ -219,7 +214,7 @@ function setCircleZwo(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
};
|
||||||
function setCircleThree(){
|
function setCircleThree(){
|
||||||
try {
|
try {
|
||||||
if(document.getElementById("box3").style.backgroundColor == "green"){
|
if(document.getElementById("box3").style.backgroundColor == "green"){
|
||||||
@@ -231,7 +226,7 @@ function setCircleThree(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
};
|
||||||
function setCircleFour(){
|
function setCircleFour(){
|
||||||
try {
|
try {
|
||||||
if(document.getElementById("box4").style.backgroundColor == "green"){
|
if(document.getElementById("box4").style.backgroundColor == "green"){
|
||||||
@@ -242,7 +237,7 @@ function setCircleFour(){
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-5
@@ -25,7 +25,6 @@ function checkBoxes() {
|
|||||||
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]);
|
||||||
var pathToLower = pathTest.toLowerCase();
|
var pathToLower = pathTest.toLowerCase();
|
||||||
if(testEndings.some(e => pathToLower.endsWith(e))){
|
if(testEndings.some(e => pathToLower.endsWith(e))){
|
||||||
document.getElementById("progressbar").style.visibility = "visible";
|
|
||||||
//assembly of the json for the main
|
//assembly of the json for the main
|
||||||
|
|
||||||
const selectedStyles = [checkedCounter];
|
const selectedStyles = [checkedCounter];
|
||||||
@@ -49,15 +48,15 @@ function checkBoxes() {
|
|||||||
const sendingPackage = {
|
const sendingPackage = {
|
||||||
"video": {
|
"video": {
|
||||||
"module":"extraction-video-to-audio",
|
"module":"extraction-video-to-audio",
|
||||||
"inputVideoPath": pathTest,
|
"inputVideoPath": pathTest
|
||||||
"outputType": outputType.value
|
|
||||||
},
|
},
|
||||||
"transcription": {
|
"transcription": {
|
||||||
"module": transcriptionType.value
|
"module": transcriptionType.value
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"module":aiType.value,
|
"module":aiType.value,
|
||||||
"styles": selectedStyles
|
"styles": selectedStyles,
|
||||||
|
"outputType": outputType.value
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.submit.submit(sendingPackage)
|
window.submit.submit(sendingPackage)
|
||||||
@@ -105,7 +104,6 @@ function changeLanguage(language) {
|
|||||||
function handleFiles(files) {
|
function handleFiles(files) {
|
||||||
try {
|
try {
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
document.getElementById("progressbar").style.visibility = "visible";
|
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
if (file.type.startsWith('video/')) {
|
if (file.type.startsWith('video/')) {
|
||||||
const filePath = window.explorer.onFileDrop(files[0])
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,10 +124,12 @@ electron.ipcMain.handle('get-module-names', async () => {
|
|||||||
// mainWindow.webContents.send("modules", module_array)
|
// mainWindow.webContents.send("modules", module_array)
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
var globalArgs = {}
|
||||||
|
var globalFinalHtmlPath = ""
|
||||||
|
|
||||||
electron.ipcMain.on("file_submit", async (event, args) => {
|
electron.ipcMain.on("file_submit", async (event, args) => {
|
||||||
try {
|
try {
|
||||||
|
globalArgs = args
|
||||||
let curstep = 0
|
let curstep = 0
|
||||||
let totalsteps = 3 + args.document.styles.length
|
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 => {
|
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);
|
console.log(resp);
|
||||||
transcriptpath = resp
|
globalFinalHtmlPath = resp
|
||||||
curstep++
|
curstep++
|
||||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@@ -196,6 +198,11 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: transcriptpath }).then(resp => {
|
||||||
|
mainWindow.webContents.send("submitSpeaker", resp)
|
||||||
|
console.log(resp)
|
||||||
|
})
|
||||||
|
|
||||||
// TODO actually implement this functionality
|
// TODO actually implement this functionality
|
||||||
// Module to get the first few lines for each speaker to send to the frontend
|
// 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 => {
|
// await mapFunctions.get("speaker-getter-idfk").function(transcriptpath).then(resp => {
|
||||||
@@ -208,7 +215,7 @@ electron.ipcMain.on("file_submit", async (event, args) => {
|
|||||||
// // speakerA: {source: "Pfad zur Audio File"},
|
// // speakerA: {source: "Pfad zur Audio File"},
|
||||||
// // speakerB:.....
|
// // speakerB:.....
|
||||||
// // }
|
// // }
|
||||||
mainWindow.webContents.send("speakers", {speakerA:"pfad1", speakerB:"pfad2"})
|
// mainWindow.webContents.send("speakers", {speakerA:"pfad1", speakerB:"pfad2"})
|
||||||
// }).catch(err => {
|
// }).catch(err => {
|
||||||
// mainWindow.webContents.send("error", err)
|
// mainWindow.webContents.send("error", err)
|
||||||
// return
|
// return
|
||||||
@@ -220,6 +227,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 =
|
let q =
|
||||||
|
|||||||
Generated
+5
-4
@@ -15,7 +15,7 @@
|
|||||||
"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.3.0",
|
||||||
"fluent-ffmpeg": "^2.1.3",
|
"fluent-ffmpeg": "^2.1.3",
|
||||||
"html-to-docx": "^1.8.0",
|
"html-to-docx": "^1.8.0",
|
||||||
"mocha": "^11.7.5",
|
"mocha": "^11.7.5",
|
||||||
@@ -1773,9 +1773,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ffmpeg-static": {
|
"node_modules/ffmpeg-static": {
|
||||||
"version": "5.2.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.3.0.tgz",
|
||||||
"integrity": "sha512-WrM7kLW+do9HLr+H6tk7LzQ7kPqbAgLjdzNE32+u3Ff11gXt9Kkkd2nusGFrlWMIe+XaA97t+I8JS7sZIrvRgA==",
|
"integrity": "sha512-H+K6sW6TiIX6VGend0KQwthe+kaceeH/luE8dIZyOP35ik7ahYojDuqlTV1bOrtEwl01sy2HFNGQfi5IDJvotg==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1832,6 +1832,7 @@
|
|||||||
"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",
|
||||||
"integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==",
|
"integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==",
|
||||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^0.2.9",
|
"async": "^0.2.9",
|
||||||
"which": "^1.1.1"
|
"which": "^1.1.1"
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"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.3.0",
|
||||||
"fluent-ffmpeg": "^2.1.3",
|
"fluent-ffmpeg": "^2.1.3",
|
||||||
"html-to-docx": "^1.8.0",
|
"html-to-docx": "^1.8.0",
|
||||||
"mocha": "^11.7.5",
|
"mocha": "^11.7.5",
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
const ffmpeg = require("fluent-ffmpeg");
|
||||||
|
const ffmpegPath = require("ffmpeg-static");
|
||||||
|
|
||||||
|
ffmpeg.setFfmpegPath(ffmpegPath);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "extract-speaker-snippets",
|
||||||
|
type: "audio",
|
||||||
|
displayname: "Extract Speaker Snippets",
|
||||||
|
|
||||||
|
async function(parameter) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
|
||||||
|
let output = {}
|
||||||
|
|
||||||
|
console.log("Extract Speaker Snippets\n");
|
||||||
|
|
||||||
|
// Pfade
|
||||||
|
const AUDIO_PATH = parameter.audioPath; // Gesamt-Audio
|
||||||
|
const JSON_PATH = parameter.jsonPath; // json summary
|
||||||
|
const OUTPUT_DIR = path.join(__dirname, "/../../../storage/audio/speakerSnippets");
|
||||||
|
|
||||||
|
|
||||||
|
if (!AUDIO_PATH || !JSON_PATH) {
|
||||||
|
console.error("no audioPath or jsonPath available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output-Ordner
|
||||||
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||||
|
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON laden
|
||||||
|
let entries;
|
||||||
|
try {
|
||||||
|
entries = JSON.parse(fs.readFileSync(JSON_PATH, "utf8"));
|
||||||
|
} catch (err) {
|
||||||
|
console.error("JSON reading failed", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(entries)) {
|
||||||
|
console.error("JSON is not an Array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pro Speaker genau EINEN Satz merken
|
||||||
|
const speakerMap = {};
|
||||||
|
|
||||||
|
for (const item of entries) {
|
||||||
|
if (!speakerMap[item.speaker]) {
|
||||||
|
speakerMap[item.speaker] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFmpeg pro Speaker ausführen (sequenziell)
|
||||||
|
for (const speaker of Object.keys(speakerMap)) {
|
||||||
|
const data = speakerMap[speaker];
|
||||||
|
|
||||||
|
// ms → Sekunden
|
||||||
|
const startSec = data.start / 1000;
|
||||||
|
const durationSec = (data.end - data.start) / 1000;
|
||||||
|
|
||||||
|
if (durationSec <= 0) {
|
||||||
|
console.log(`invalid times for Speaker ${speaker}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const outFile = path.join(OUTPUT_DIR, `speaker_${speaker}.wav`);
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
ffmpeg(AUDIO_PATH)
|
||||||
|
.setStartTime(startSec)
|
||||||
|
.setDuration(durationSec)
|
||||||
|
.output(outFile)
|
||||||
|
.on("end", () => {
|
||||||
|
output[`speaker${speaker}`] = {src: outFile, name: `speaker${speaker}`}
|
||||||
|
console.log(`Snippet erstellt: speaker_${speaker}.wav`);
|
||||||
|
res();
|
||||||
|
})
|
||||||
|
.on("error", (err) => {
|
||||||
|
console.error(`FFmpeg Fehler (${speaker})`, err.message);
|
||||||
|
rej();
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
resolve(output)
|
||||||
|
console.log("\nAlle Speaker-Snippets erstellt\n");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
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)) {
|
if (!fs.existsSync(outputDir)) {
|
||||||
fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist
|
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"
|
// 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_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 = {
|
const module_exports = {
|
||||||
name: "llm-saia_openai_gpt",
|
name: "llm-saia_openai_gpt",
|
||||||
@@ -19,66 +18,72 @@ const module_exports = {
|
|||||||
description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform",
|
description: "Generates documents using OpenAI GPT OSS 120B via SAIA platform",
|
||||||
|
|
||||||
async function(parameter) {
|
async function(parameter) {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
console.log("SAIA OpenAI GPT module invoked with parameters:", parameter);
|
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
|
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) {
|
||||||
|
// 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
|
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
||||||
try {
|
return new Promise(async(resolve, reject) => {
|
||||||
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
try {
|
||||||
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path
|
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
||||||
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed
|
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 ---
|
// --- REST CALL ---
|
||||||
const response = await fetch(SAIA_URL, {
|
const response = await fetch(SAIA_URL, { //safe model response in variable
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: "openai-gpt-oss-120b",
|
model: "openai-gpt-oss-120b",
|
||||||
messages: [
|
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: "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 }
|
{ role: "user", content: promptText }
|
||||||
],
|
],
|
||||||
temperature: 0
|
temperature: 0
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) { //ok is true when a response was successful
|
if (!response.ok) { //ok is true when a responce was successfull
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
throw new Error(`SAIA API error (${response.status}): ${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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const module_exports = {
|
|||||||
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}.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
|
fs.writeFileSync(outPath, output, "utf8"); // Write output to file
|
||||||
|
|
||||||
// console.log("Generated document written to:", outPath);
|
// console.log("Generated document written to:", outPath);
|
||||||
|
|||||||
@@ -18,66 +18,72 @@ const module_exports = {
|
|||||||
description: "Generates documents using QWEN 3 235B via SAIA platform",
|
description: "Generates documents using QWEN 3 235B via SAIA platform",
|
||||||
|
|
||||||
async function(parameter) {
|
async function(parameter) {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
|
try {
|
||||||
|
// console.log("SAIA QWEN 3 235B module invoked with parameters:", parameter);
|
||||||
|
|
||||||
await this.createDocumentFromTranscript( // Call the function to create document with transcript, document type and language
|
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) {
|
||||||
|
// 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
|
createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English
|
||||||
try {
|
return new Promise(async(resolve, reject) => {
|
||||||
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); // read transcript file from Path
|
try {
|
||||||
const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); // read document type from Path
|
const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path
|
||||||
const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; // combine doc type, language and transcript - Change prompt here if needed
|
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 ---
|
// --- REST CALL ---
|
||||||
const response = await fetch(SAIA_URL, {
|
const response = await fetch(SAIA_URL, { //safe model response in variable
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
"Authorization": `Bearer ${SAIA_API_KEY}`,
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: "qwen3-235b-a22b",
|
model: "qwen3-235b-a22b",
|
||||||
messages: [
|
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: "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 }
|
{ role: "user", content: promptText }
|
||||||
],
|
],
|
||||||
temperature: 0
|
temperature: 0
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) { // ok is true when a response was successful
|
if (!response.ok) { //ok is true when a responce was successfull
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
throw new Error(`SAIA API error (${response.status}): ${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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ module.exports = {
|
|||||||
// let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav');
|
// let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav');
|
||||||
|
|
||||||
// let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'});
|
// let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'});
|
||||||
|
// let snippets = await mapFunctions.get("extract-speaker-snippets").function({audioPath:'/Users/santa/Proj25/video2document/storage/audio/KittyKat.wav', jsonPath1: '/Users/santa/Proj25/video2document/storage/transcriptionSummaries/KittyKat-1765806474958.json' });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,25 @@
|
|||||||
|
Du bist ein erfahrener Moderator und Projektmanager.
|
||||||
|
|
||||||
|
AUFGABE:
|
||||||
|
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem folgenden Transkript.
|
||||||
|
|
||||||
|
ANFORDERUNGEN:
|
||||||
|
- Rekonstruiere die tatsächlichen Themenblöcke
|
||||||
|
- Ordne sie logisch und chronologisch
|
||||||
|
- Fasse ähnliche Diskussionen zusammen
|
||||||
|
- Keine irrelevanten Details aufnehmen
|
||||||
|
|
||||||
|
STRUKTUR:
|
||||||
|
- Titel der Agenda
|
||||||
|
- Ziel des Meetings (1–2 Sätze)
|
||||||
|
- Agenda-Punkte (nummeriert)
|
||||||
|
- Thema
|
||||||
|
- Kurzbeschreibung
|
||||||
|
- Ziel des Punktes (Information, Entscheidung, Diskussion)
|
||||||
|
|
||||||
|
STIL:
|
||||||
|
- Klar, kompakt
|
||||||
|
- Business-orientiert
|
||||||
|
- Keine Sprecher- oder Zeitangaben
|
||||||
|
|
||||||
|
TRANSKRIPT:
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
Du bist ein intelligenter Dokumenten-Generator.
|
||||||
|
|
||||||
|
AUFGABE:
|
||||||
|
Erstelle ein individuelles Dokument basierend auf:
|
||||||
|
1) dem Meeting-Transkript
|
||||||
|
2) der zusätzlichen Nutzeranweisung
|
||||||
|
|
||||||
|
WICHTIG:
|
||||||
|
- Priorisiere die Nutzeranweisung
|
||||||
|
- Nutze das Transkript als Wissensquelle
|
||||||
|
- Struktur, Tonalität und Detailgrad anpassen
|
||||||
|
- Inhalte logisch zusammenführen
|
||||||
|
|
||||||
|
FORMAT:
|
||||||
|
- Passe Struktur und Stil an den Nutzerwunsch an
|
||||||
|
- Klare Überschriften
|
||||||
|
- Keine Sprecher- oder Zeitangaben
|
||||||
|
|
||||||
|
TRANSKRIPT & NUTZERANWEISUNG:
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Du bist ein professioneller Protokollführer.
|
||||||
|
|
||||||
|
AUFGABE:
|
||||||
|
Erstelle ein Ergebnisprotokoll basierend auf dem Meeting-Transkript.
|
||||||
|
|
||||||
|
FOKUS:
|
||||||
|
- Ergebnisse statt Diskussionen
|
||||||
|
- Entscheidungen, Beschlüsse, Vereinbarungen
|
||||||
|
- Klare, überprüfbare Aussagen
|
||||||
|
|
||||||
|
STRUKTUR:
|
||||||
|
1. Meeting-Informationen
|
||||||
|
2. Ergebnisse je Thema
|
||||||
|
- Thema
|
||||||
|
- Ergebnis / Beschluss
|
||||||
|
3. Entscheidungen
|
||||||
|
4. Aufgaben & Verantwortlichkeiten
|
||||||
|
5. Offene Punkte
|
||||||
|
|
||||||
|
REGELN:
|
||||||
|
- Keine Meinungen oder Spekulationen
|
||||||
|
- Keine Zeit- oder Sprecherangaben
|
||||||
|
- Sachlich, formal
|
||||||
|
|
||||||
|
TRANSKRIPT:
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
Du bist ein erfahrener Scrum Master.
|
||||||
|
|
||||||
|
AUFGABE:
|
||||||
|
Erstelle Sprint Planning Notes aus dem folgenden Meeting-Transkript.
|
||||||
|
|
||||||
|
FOKUS:
|
||||||
|
- Sprint-Ziele
|
||||||
|
- User Stories / Tasks
|
||||||
|
- Abhängigkeiten
|
||||||
|
- Risiken
|
||||||
|
- Commitments
|
||||||
|
|
||||||
|
STRUKTUR:
|
||||||
|
1. Sprint Overview
|
||||||
|
- Sprint-Ziel
|
||||||
|
- Zeitraum (falls erwähnt)
|
||||||
|
|
||||||
|
2. Geplante Arbeit
|
||||||
|
- User Story / Task
|
||||||
|
- Beschreibung
|
||||||
|
- Akzeptanzkriterien (falls ableitbar)
|
||||||
|
|
||||||
|
3. Abhängigkeiten & Blocker
|
||||||
|
|
||||||
|
4. Risiken & Annahmen
|
||||||
|
|
||||||
|
5. Vereinbarungen / Team-Commitments
|
||||||
|
|
||||||
|
STIL:
|
||||||
|
- Agile-konform
|
||||||
|
- Klar & umsetzungsorientiert
|
||||||
|
- Bullet Points bevorzugen
|
||||||
|
|
||||||
|
TRANSKRIPT:
|
||||||
@@ -1,217 +1,44 @@
|
|||||||
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
|
Du bist ein professioneller Meeting-Analyst und Business Writer.
|
||||||
Output ONLY the final .md document — no meta comments, no explanations.
|
|
||||||
|
|
||||||
Follow exactly the STRUCTURE defined below.
|
AUFGABE:
|
||||||
Follow exactly the STYLE rules.
|
Erstelle einen strukturierten Follow-up Report basierend auf dem folgenden Meeting-Transkript.
|
||||||
Use timestamps in HH:MM:SS format.
|
|
||||||
If information is missing, use: Unclear:<reason>.
|
|
||||||
|
|
||||||
==================== STRUCTURE & RULES ====================
|
ANFORDERUNGEN:
|
||||||
|
- Fasse Inhalte sinngemäß zusammen
|
||||||
|
- Entferne Redundanzen und Smalltalk
|
||||||
|
- Formuliere klar, präzise und professionell
|
||||||
|
- Verwende neutrale Business-Sprache
|
||||||
|
- Keine Zeitstempel oder Sprecher-Namen zitieren
|
||||||
|
- Leite Entscheidungen und Aufgaben logisch ab, wenn sie implizit sind
|
||||||
|
- Markiere offene Punkte klar
|
||||||
|
|
||||||
{
|
STRUKTUR DES DOKUMENTS:
|
||||||
"FORMAT": "HTML",
|
1. Titel & Metadaten
|
||||||
|
- Meetingtitel (ableiten)
|
||||||
|
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben“)
|
||||||
|
- Teilnehmer (zusammengefasst)
|
||||||
|
|
||||||
"STRUCTURE": {
|
2. Executive Summary (max. 5 Bullet Points)
|
||||||
"titlepage": [
|
|
||||||
"title",
|
|
||||||
"date",
|
|
||||||
"start",
|
|
||||||
"end",
|
|
||||||
"duration",
|
|
||||||
"location",
|
|
||||||
"host",
|
|
||||||
"participants"
|
|
||||||
],
|
|
||||||
|
|
||||||
"toc": "[section](#anchor) — HH:MM:SS",
|
3. Besprochene Themen
|
||||||
|
- Thema
|
||||||
|
- Kernaussagen
|
||||||
|
- Relevante Erkenntnisse
|
||||||
|
|
||||||
"section": {
|
4. Entscheidungen
|
||||||
"h2": "<topic> — HH:MM:SS",
|
- Entscheidung
|
||||||
"summary": "exactly 1 concise sentence",
|
- Kontext / Begründung
|
||||||
"key_points": "maximum 5 bullet points; quotes optional",
|
|
||||||
"decisions": "list items formatted as: decision text | owner | due date",
|
|
||||||
"actions": "HTML table: id | task | owner | due | status"
|
|
||||||
},
|
|
||||||
|
|
||||||
"exec_summary": "exactly 3 short sentences",
|
5. Action Items
|
||||||
|
- Aufgabe
|
||||||
|
- Verantwortlich (falls ableitbar)
|
||||||
|
- Ziel / Zweck
|
||||||
|
|
||||||
"consolidated": [
|
6. Offene Fragen & Risiken
|
||||||
"decisions",
|
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
|
|
||||||
"appendix": "optional"
|
STIL:
|
||||||
},
|
- Überschriften klar strukturiert
|
||||||
|
- Bullet Points bevorzugen
|
||||||
|
- Präzise, keine Umgangssprache
|
||||||
|
|
||||||
"STYLE": {
|
TRANSKRIPT:
|
||||||
"tone": "neutral, concise, professional",
|
|
||||||
"ts_format": "HH:MM:SS",
|
|
||||||
"no_meta": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROCESS": {
|
|
||||||
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
|
|
||||||
"speakers": "use names if available; else Speaker X",
|
|
||||||
"long_transcripts": "split → summarize → merge",
|
|
||||||
"unclear": "Unclear:<reason>"
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
|
|
||||||
}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Insert all generated content into the following HTML TEMPLATE:
|
|
||||||
|
|
||||||
# {{title}}
|
|
||||||
|
|
||||||
**Date:** {{date}}
|
|
||||||
**Start:** {{start}}
|
|
||||||
**End:** {{end}}
|
|
||||||
**Duration:** {{duration}}
|
|
||||||
**Location:** {{location}}
|
|
||||||
**Host:** {{host}}
|
|
||||||
**Participants:** {{participants}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
{{toc}}
|
|
||||||
|
|
||||||
---
|
|
||||||
Generate a structured meeting report in HTML using STRUCTURE and STYLE.
|
|
||||||
Output ONLY the final .md document — no meta comments, no explanations.
|
|
||||||
|
|
||||||
Follow exactly the STRUCTURE defined below.
|
|
||||||
Follow exactly the STYLE rules.
|
|
||||||
Use timestamps in HH:MM:SS format.
|
|
||||||
If information is missing, use: UNKLAR:<reason>.
|
|
||||||
|
|
||||||
==================== STRUCTURE & RULES ====================
|
|
||||||
|
|
||||||
{
|
|
||||||
"FORMAT": "HTML",
|
|
||||||
|
|
||||||
"STRUCTURE": {
|
|
||||||
"titlepage": [
|
|
||||||
"title",
|
|
||||||
"date",
|
|
||||||
"start",
|
|
||||||
"end",
|
|
||||||
"duration",
|
|
||||||
"location",
|
|
||||||
"host",
|
|
||||||
"participants"
|
|
||||||
],
|
|
||||||
|
|
||||||
"toc": "[section](#anchor) — HH:MM:SS",
|
|
||||||
|
|
||||||
"section": {
|
|
||||||
"h2": "<topic> — HH:MM:SS",
|
|
||||||
"summary": "exactly 1 concise sentence",
|
|
||||||
"key_points": "maximum 5 bullet points; quotes optional",
|
|
||||||
"decisions": "list items formatted as: decision text | owner | due date",
|
|
||||||
"actions": "HTML table: id | task | owner | due | status"
|
|
||||||
},
|
|
||||||
|
|
||||||
"exec_summary": "exactly 3 short sentences",
|
|
||||||
|
|
||||||
"consolidated": [
|
|
||||||
"decisions",
|
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
|
|
||||||
"appendix": "optional"
|
|
||||||
},
|
|
||||||
|
|
||||||
"STYLE": {
|
|
||||||
"tone": "neutral, concise, professional",
|
|
||||||
"ts_format": "HH:MM:SS",
|
|
||||||
"no_meta": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROCESS": {
|
|
||||||
"timestamps": "use transcript timestamps if present; otherwise estimate minimal",
|
|
||||||
"speakers": "use names if available; else Speaker X",
|
|
||||||
"long_transcripts": "split → summarize → merge",
|
|
||||||
"unclear": "UNKLAR:<reason>"
|
|
||||||
},
|
|
||||||
|
|
||||||
"PROMPT_SNIPPET": "Generate meeting report in HTML using STRUCTURE and STYLE. Output only the report."
|
|
||||||
}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Insert all generated content into the following HTML TEMPLATE:
|
|
||||||
|
|
||||||
# {{title}}
|
|
||||||
|
|
||||||
**Date:** {{date}}
|
|
||||||
**Start:** {{start}}
|
|
||||||
**End:** {{end}}
|
|
||||||
**Duration:** {{duration}}
|
|
||||||
**Location:** {{location}}
|
|
||||||
**Host:** {{host}}
|
|
||||||
**Participants:** {{participants}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
{{toc}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
{{exec_summary}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sections
|
|
||||||
{{sections}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Decisions
|
|
||||||
{{consolidated_decisions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Actions
|
|
||||||
{{consolidated_actions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix
|
|
||||||
{{appendix}}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Final Requirement:
|
|
||||||
Output ONLY the completed HTML meeting report.
|
|
||||||
## Executive Summary
|
|
||||||
{{exec_summary}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sections
|
|
||||||
{{sections}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Decisions
|
|
||||||
{{consolidated_decisions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consolidated Actions
|
|
||||||
{{consolidated_actions}}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix
|
|
||||||
{{appendix}}
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
Final Requirement:
|
|
||||||
Output ONLY the completed HTML meeting report.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user