mirror of
https://gitlab.rlp.net/proj-wise2526-video2document/video2document.git
synced 2026-06-15 18:01:52 +02:00
Remade replace Speaker module which now takes the premade speaker mapping json and directly replaces speakers in the document. Also refined the Standard documents so consistency is improved
This commit is contained in:
@@ -1,81 +1,72 @@
|
||||
// Loading required packages
|
||||
require("./requires.js")
|
||||
require("./requires.js");
|
||||
console.log(start);
|
||||
|
||||
|
||||
// Initialising map to be used to store the functionality later on for reloadability
|
||||
mapFunctions = new Map()
|
||||
|
||||
mapFunctions = new Map();
|
||||
|
||||
// Loading the Function Map
|
||||
var path = `${mainDir}/services/modules`
|
||||
var path = `${mainDir}/services/modules`;
|
||||
var folders = fs.readdirSync(path).filter(function (file) {
|
||||
return fs.statSync(path+'/'+file).isDirectory();
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// The startup information for the project, here you can add stuff that might be nice to see when the app starts
|
||||
mapFunctions.get("Startup_function").function()
|
||||
console.log("------------------------------------ Status ------------------------------------");
|
||||
mapFunctions.get("Startup_function").function();
|
||||
console.log(
|
||||
"------------------------------------ Status ------------------------------------"
|
||||
);
|
||||
console.log(__dirname);
|
||||
console.log(platform);
|
||||
console.log(`The Startup took ${new Date() - start}ms`)
|
||||
console.log(`The Startup took ${new Date() - start}ms`);
|
||||
console.log(`${mapFunctions.size} Function modules loaded`);
|
||||
console.log("--------------------------------------------------------------------------------");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
console.log(
|
||||
"--------------------------------------------------------------------------------"
|
||||
);
|
||||
|
||||
// --------------------------------------------------------- CLI COMMANDS --------------------------------------------------------- //
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
|
||||
rl.on("line", data =>{
|
||||
const args = data.trim().split(" ");
|
||||
const command = args.shift().toLowerCase();
|
||||
mapFunctions.get("cliCommands").function(command, args)
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
rl.on("line", (data) => {
|
||||
const args = data.trim().split(" ");
|
||||
const command = args.shift().toLowerCase();
|
||||
mapFunctions.get("cliCommands").function(command, args);
|
||||
});
|
||||
|
||||
// ----------------------------------------------------------- ELECTRON ----------------------------------------------------------- //
|
||||
|
||||
let mainWindow;
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: `${mainDir}/electron/main/preload.js`
|
||||
}
|
||||
});
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: `${mainDir}/electron/main/preload.js`,
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.loadFile('./electron/main/index.html');
|
||||
mainWindow.loadFile("./electron/main/index.html");
|
||||
}
|
||||
|
||||
electron.app.whenReady().then(createWindow);
|
||||
|
||||
|
||||
// electron.ipcMain.on("extract", (event, args) => {
|
||||
// mapFunctions.get("extraction-video-to-audio").function(args)
|
||||
// })
|
||||
@@ -84,26 +75,31 @@ electron.app.whenReady().then(createWindow);
|
||||
// mainWindow.webContents.send("fuck", "worked uwu")
|
||||
// }, 5000);
|
||||
|
||||
electron.ipcMain.handle('get-module-names', async () => {
|
||||
let module_array = {
|
||||
"ai_modules":[],
|
||||
"transcription_modules":[]
|
||||
electron.ipcMain.handle("get-module-names", async () => {
|
||||
let module_array = {
|
||||
ai_modules: [],
|
||||
transcription_modules: [],
|
||||
};
|
||||
mapFunctions.forEach((e) => {
|
||||
switch (e.type) {
|
||||
case "llm":
|
||||
module_array.ai_modules.push({
|
||||
name: e.name,
|
||||
displayname: e.displayname,
|
||||
});
|
||||
break;
|
||||
case "transcription":
|
||||
module_array.transcription_modules.push({
|
||||
name: e.name,
|
||||
displayname: e.displayname,
|
||||
});
|
||||
break;
|
||||
}
|
||||
mapFunctions.forEach(e => {
|
||||
switch(e.type){
|
||||
case "llm":
|
||||
module_array.ai_modules.push({"name": e.name, "displayname": e.displayname})
|
||||
break;
|
||||
case "transcription":
|
||||
module_array.transcription_modules.push({"name": e.name, "displayname": e.displayname})
|
||||
break;
|
||||
}
|
||||
})
|
||||
// console.log(module_array);
|
||||
return module_array
|
||||
});
|
||||
// console.log(module_array);
|
||||
return module_array;
|
||||
});
|
||||
|
||||
|
||||
// electron.ipcMain.on("get_modules", async (event, args) => {
|
||||
// let module_array = {
|
||||
// "ai_modules":[],
|
||||
@@ -124,165 +120,219 @@ electron.ipcMain.handle('get-module-names', async () => {
|
||||
// mainWindow.webContents.send("modules", module_array)
|
||||
// })
|
||||
|
||||
var globalArgs = {}
|
||||
var globalFinalHtmlPath = ""
|
||||
var globalArgs = {};
|
||||
var globalFinalHtmlPath = "";
|
||||
|
||||
electron.ipcMain.on("file_submit", async (event, args) => {
|
||||
try {
|
||||
globalArgs = args
|
||||
let curstep = 0
|
||||
let totalsteps = 4
|
||||
try {
|
||||
globalArgs = args;
|
||||
let curstep = 0;
|
||||
let totalsteps = 4;
|
||||
|
||||
const TEMPLATE_MAP = {
|
||||
"followup-report": "followup_report.txt",
|
||||
"agenda": "agenda.txt",
|
||||
"result-protocol": "result_protocol.txt",
|
||||
"sprint-planning": "sprint_planning_note.txt",
|
||||
"custom": "custom_document.txt"
|
||||
};
|
||||
const TEMPLATE_MAP = {
|
||||
"followup-report": "followup_report.txt",
|
||||
agenda: "agenda.txt",
|
||||
"result-protocol": "result_protocol.txt",
|
||||
"sprint-planning": "sprint_planning_note.txt",
|
||||
custom: "custom_document.txt",
|
||||
};
|
||||
|
||||
const templateFile = TEMPLATE_MAP[args.document.type];
|
||||
const templateFile = TEMPLATE_MAP[args.document.type];
|
||||
|
||||
if (!templateFile) {
|
||||
throw new Error("Unknown document type: " + args.document.type);
|
||||
}
|
||||
|
||||
console.log(args);
|
||||
let audiopath = ""
|
||||
let transcriptpath = ""
|
||||
|
||||
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: mapFunctions.get(args.transcription.module).audioformat}).then(resp => {
|
||||
console.log(resp);
|
||||
audiopath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
console.log("\n\n Running the Audio to Transcription module");
|
||||
// TODO implement transcription module
|
||||
// This code handles the Audio to Text transcription module call
|
||||
await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
console.log("\n\n Running the Transcription Summarizer module");
|
||||
// This code summarises the transcript, so that it can be used by an llm
|
||||
// await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => {
|
||||
await mapFunctions.get("summarize-transcription2").function(transcriptpath).then(resp => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
console.log("\n\n Running the LLM module");
|
||||
// TODO implement documentation module
|
||||
// This code handles the Text to Document processing module call
|
||||
|
||||
console.log(`\n\n Running the LLM for Document Style ${args.document.type}`);
|
||||
|
||||
await mapFunctions.get("module-handler").function(args.document.module, { inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/" + templateFile, language: "en" }).then(resp => {
|
||||
console.log(resp);
|
||||
globalFinalHtmlPath = resp
|
||||
curstep++
|
||||
mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps})
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
|
||||
|
||||
await mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: transcriptpath }).then(resp => {
|
||||
mainWindow.webContents.send("speakerAudios", resp)
|
||||
}).catch(err => {
|
||||
mainWindow.webContents.send("error", err)
|
||||
console.log(err);
|
||||
return
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (!templateFile) {
|
||||
throw new Error("Unknown document type: " + args.document.type);
|
||||
}
|
||||
})
|
||||
|
||||
electron.ipcMain.on("file_download", async() => {
|
||||
await mapFunctions.get("htmlDocumentConverter").convert({inputPath:globalFinalHtmlPath, format: globalArgs.document.outputType, showDialog: true});
|
||||
})
|
||||
console.log(args);
|
||||
let audiopath = "";
|
||||
let transcriptpath = "";
|
||||
|
||||
electron.ipcMain.on("speaker_submit", async() => {
|
||||
console.log("\n\n\nJa also hier kam was an \n\n\n");
|
||||
})
|
||||
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: mapFunctions.get(args.transcription.module).audioformat,
|
||||
})
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
audiopath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
let q =
|
||||
{
|
||||
video: {
|
||||
module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio
|
||||
inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like
|
||||
outputType: "String" // The file format to be used for the audio output file, such as wav, mp3, flac and so on
|
||||
},
|
||||
transcription:{
|
||||
module: "String" // The module name of the transcription model you want to use
|
||||
},
|
||||
document:{
|
||||
module: "String", // The module name of the AI model you want to use to create the document
|
||||
styles: [ // An array of all the document styles/prompts you want to have the document be processed with
|
||||
{
|
||||
prompt: "String",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
console.log("\n\n Running the Audio to Transcription module");
|
||||
// TODO implement transcription module
|
||||
// This code handles the Audio to Text transcription module call
|
||||
await mapFunctions
|
||||
.get("module-handler")
|
||||
.function(args.transcription.module, audiopath)
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
console.log("\n\n Running the Transcription Summarizer module");
|
||||
// This code summarises the transcript, so that it can be used by an llm
|
||||
// await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => {
|
||||
await mapFunctions
|
||||
.get("summarize-transcription2")
|
||||
.function(transcriptpath)
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
transcriptpath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
console.log("\n\n Running the LLM module");
|
||||
// TODO implement documentation module
|
||||
// This code handles the Text to Document processing module call
|
||||
|
||||
console.log(
|
||||
`\n\n Running the LLM for Document Style ${args.document.type}`
|
||||
);
|
||||
|
||||
await mapFunctions
|
||||
.get("module-handler")
|
||||
.function(args.document.module, {
|
||||
inputTranscriptPath: transcriptpath,
|
||||
documentTypePath: "./storage/documentType/" + templateFile,
|
||||
language: "en",
|
||||
})
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
globalFinalHtmlPath = resp;
|
||||
curstep++;
|
||||
mainWindow.webContents.send("progress", {
|
||||
curstep: curstep,
|
||||
totalsteps: totalsteps,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
await mapFunctions
|
||||
.get("extract-speaker-snippets")
|
||||
.function({ audioPath: audiopath, jsonPath: transcriptpath })
|
||||
.then((resp) => {
|
||||
mainWindow.webContents.send("speakerAudios", resp);
|
||||
})
|
||||
.catch((err) => {
|
||||
mainWindow.webContents.send("error", err);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("file_download", async () => {
|
||||
await mapFunctions
|
||||
.get("htmlDocumentConverter")
|
||||
.convert({
|
||||
inputPath: globalFinalHtmlPath,
|
||||
format: globalArgs.document.outputType,
|
||||
showDialog: true,
|
||||
});
|
||||
});
|
||||
|
||||
electron.ipcMain.on("speaker_submit", async (event, args) => {
|
||||
console.log("\n\n\nJa also hier kam was an \n\n\n");
|
||||
console.log(args);
|
||||
|
||||
try {
|
||||
await mapFunctions.get("replace_speaker").function(args);
|
||||
event.reply("speaker_submit_response", { success: true });
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
event.reply("speaker_submit_response", {
|
||||
success: false,
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let q = {
|
||||
video: {
|
||||
module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio
|
||||
inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like
|
||||
outputType: "String", // The file format to be used for the audio output file, such as wav, mp3, flac and so on
|
||||
},
|
||||
transcription: {
|
||||
module: "String", // The module name of the transcription model you want to use
|
||||
},
|
||||
document: {
|
||||
module: "String", // The module name of the AI model you want to use to create the document
|
||||
styles: [
|
||||
// An array of all the document styles/prompts you want to have the document be processed with
|
||||
{
|
||||
prompt: "String",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
let q1 = {
|
||||
"ai_modules": [
|
||||
{name:"abc", displayname:"ABC"},
|
||||
{name:"qeg", displayname:"aqghegahu"}
|
||||
],
|
||||
"transcription_modules": [
|
||||
{name:"abc", displayname:"ABC"},
|
||||
{name:"qeg", displayname:"aqghegahu"}
|
||||
]
|
||||
}
|
||||
ai_modules: [
|
||||
{ name: "abc", displayname: "ABC" },
|
||||
{ name: "qeg", displayname: "aqghegahu" },
|
||||
],
|
||||
transcription_modules: [
|
||||
{ name: "abc", displayname: "ABC" },
|
||||
{ name: "qeg", displayname: "aqghegahu" },
|
||||
],
|
||||
};
|
||||
|
||||
//gibt Documentfiles an preload zurück
|
||||
|
||||
electron.ipcMain.handle('get-txt-files', () => {
|
||||
const storagePath = `${mainDir}/storage/documentType`
|
||||
electron.ipcMain.handle("get-txt-files", () => {
|
||||
const storagePath = `${mainDir}/storage/documentType`;
|
||||
|
||||
return fs.readdirSync(storagePath)
|
||||
.filter(f => f.endsWith('.txt'))
|
||||
return fs.readdirSync(storagePath).filter((f) => f.endsWith(".txt"));
|
||||
});
|
||||
|
||||
//speichern neuer document types
|
||||
|
||||
electron.ipcMain.handle('save-txt-file', (event, fileName, content) => {
|
||||
electron.ipcMain.handle("save-txt-file", (event, fileName, content) => {
|
||||
const filePath = `${mainDir}/storage/documentType/${fileName}.txt`;
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
return true;
|
||||
});
|
||||
|
||||
//
|
||||
electron.ipcMain.handle('read-txt-file', (event, fileName) => {
|
||||
electron.ipcMain.handle("read-txt-file", (event, fileName) => {
|
||||
const filePath = `${mainDir}/storage/documentType/${fileName}`;
|
||||
return fs.readFileSync(filePath, 'utf8');
|
||||
return fs.readFileSync(filePath, "utf8");
|
||||
});
|
||||
@@ -7,35 +7,54 @@ const module_exports = {
|
||||
displayname: "Speaker Name Replacer",
|
||||
description: "Replaces speaker placeholder names with actual names based on a mapping in HTML files",
|
||||
|
||||
async function({ inputHtmlPath, speakerMappingPath }) {
|
||||
return await this.replaceNames(inputHtmlPath, speakerMappingPath);
|
||||
async function(speakerMapping) {
|
||||
// Relativ von dieser Datei aus
|
||||
const documentsDir = path.resolve(__dirname, '../../../storage/documents');
|
||||
const inputHtmlPath = await this.getNewestFile(documentsDir, '.html');
|
||||
|
||||
if (!inputHtmlPath) {
|
||||
throw new Error(`No HTML files found in ${documentsDir}`);
|
||||
}
|
||||
|
||||
return await this.replaceNames(inputHtmlPath, speakerMapping);
|
||||
},
|
||||
|
||||
replaceNames: async function(inputHtmlPath, speakerMappingPath) {
|
||||
getNewestFile: async function(dirPath, extension) {
|
||||
try {
|
||||
const files = await fs.promises.readdir(dirPath);
|
||||
const filtered = files.filter(f => f.endsWith(extension));
|
||||
|
||||
if (filtered.length === 0) return null;
|
||||
|
||||
const filesWithStats = await Promise.all(
|
||||
filtered.map(async (f) => {
|
||||
const fullPath = path.join(dirPath, f);
|
||||
const stats = await fs.promises.stat(fullPath);
|
||||
return { path: fullPath, time: stats.mtimeMs };
|
||||
})
|
||||
);
|
||||
|
||||
return filesWithStats.reduce((newest, curr) =>
|
||||
curr.time > newest.time ? curr : newest
|
||||
).path;
|
||||
} catch (error) {
|
||||
console.error("Error reading directory:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
replaceNames: async function(inputHtmlPath, speakerMapping) {
|
||||
try {
|
||||
const htmlContent = await fs.promises.readFile(inputHtmlPath, "utf-8");
|
||||
const mappingData = await fs.promises.readFile(speakerMappingPath, "utf-8");
|
||||
|
||||
let speakerMap = {};
|
||||
try {
|
||||
const parsed = JSON.parse(mappingData);
|
||||
if (parsed.speakerId && parsed.speakerName) {
|
||||
speakerMap[parsed.speakerId] = parsed.speakerName;
|
||||
} else {
|
||||
Object.assign(speakerMap, parsed);
|
||||
}
|
||||
} catch (e) {
|
||||
const lines = mappingData.trim().split('\n');
|
||||
lines.forEach(line => {
|
||||
const [placeholder, realName] = line.split(',').map(s => s.trim());
|
||||
if (placeholder && realName) speakerMap[placeholder] = realName;
|
||||
});
|
||||
}
|
||||
|
||||
let outputContent = htmlContent;
|
||||
Object.entries(speakerMap).forEach(([placeholder, realName]) => {
|
||||
const regex = new RegExp(`[\$begin:math:text$\\\\\[\]\?\$\{placeholder\}\[\\$end:math:text$\\]]?`, 'g');
|
||||
outputContent = outputContent.replace(regex, realName);
|
||||
Object.entries(speakerMapping).forEach(([placeholder, value]) => {
|
||||
// Extract name if value is an object
|
||||
const displayName = typeof value === 'string' ? value : value.name;
|
||||
|
||||
// Replace speaker placeholder with display name
|
||||
const regex = new RegExp(`\\b${placeholder}\\b`, 'g');
|
||||
outputContent = outputContent.replace(regex, displayName);
|
||||
});
|
||||
|
||||
await fs.promises.writeFile(inputHtmlPath, outputContent, "utf-8");
|
||||
@@ -50,21 +69,3 @@ const module_exports = {
|
||||
};
|
||||
|
||||
module.exports = module_exports;
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length < 2) process.exit(1);
|
||||
|
||||
const [inputHtmlPath, speakerMappingPath] = args;
|
||||
|
||||
if (!fs.existsSync(inputHtmlPath)) process.exit(1);
|
||||
if (!fs.existsSync(speakerMappingPath)) process.exit(1);
|
||||
|
||||
try {
|
||||
await module_exports.replaceNames(inputHtmlPath, speakerMappingPath);
|
||||
} catch (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
}
|
||||
@@ -1,26 +1,45 @@
|
||||
# Meeting Agenda Generator
|
||||
|
||||
Du bist ein erfahrener Moderator und Projektmanager.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem folgenden Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
ANFORDERUNGEN:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle eine sinnvolle Meeting-Agenda basierend auf dem Meeting-Transkript.
|
||||
|
||||
## ANFORDERUNGEN:
|
||||
- Rekonstruiere die tatsächlichen Themenblöcke
|
||||
- Ordne sie logisch und chronologisch
|
||||
- Fasse ähnliche Diskussionen zusammen
|
||||
- Keine irrelevanten Details aufnehmen
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
- Titel der Agenda
|
||||
- Ziel des Meetings (1–2 Sätze)
|
||||
- Agenda-Punkte (nummeriert)
|
||||
- Thema
|
||||
- Kurzbeschreibung
|
||||
- Ziel des Punktes (Information, Entscheidung, Diskussion)
|
||||
## STRUKTUR:
|
||||
|
||||
STIL:
|
||||
### 1. Titel der Agenda
|
||||
|
||||
### 2. Ziel des Meetings
|
||||
- 1–2 präzise Sätze
|
||||
|
||||
### 3. Agenda-Punkte (nummeriert)
|
||||
Für jeden Punkt:
|
||||
- **Thema**
|
||||
- **Kurzbeschreibung**
|
||||
- **Ziel des Punktes:** (Information / Entscheidung / Diskussion)
|
||||
|
||||
## STIL:
|
||||
- Klar, kompakt
|
||||
- Business-orientiert
|
||||
- Keine Sprecher- oder Zeitangaben
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Logische Reihenfolge
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,22 +1,44 @@
|
||||
# Custom Document Generator
|
||||
|
||||
Du bist ein intelligenter Dokumenten-Generator.
|
||||
|
||||
AUFGABE:
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle ein individuelles Dokument basierend auf:
|
||||
1) dem Meeting-Transkript
|
||||
2) der zusätzlichen Nutzeranweisung
|
||||
1. dem Meeting-Transkript
|
||||
2. der zusätzlichen Nutzeranweisung
|
||||
|
||||
WICHTIG:
|
||||
- Priorisiere die Nutzeranweisung
|
||||
## ANFORDERUNGEN:
|
||||
- **Priorisiere die Nutzeranweisung** über standardisierte Strukturen
|
||||
- Nutze das Transkript als Wissensquelle
|
||||
- Struktur, Tonalität und Detailgrad anpassen
|
||||
- Struktur, Tonalität und Detailgrad nach Nutzervorgabe anpassen
|
||||
- Inhalte logisch zusammenführen
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
FORMAT:
|
||||
- Passe Struktur und Stil an den Nutzerwunsch an
|
||||
- Klare Überschriften
|
||||
- Keine Sprecher- oder Zeitangaben
|
||||
## VORGEHEN:
|
||||
1. Lese die Nutzeranweisung sorgfältig
|
||||
2. Extrahiere aus dem Transkript die relevanten Informationen
|
||||
3. Erstelle das Dokument nach der gewünschten Struktur
|
||||
4. Behalte Sprecher-Platzhalter unverändert
|
||||
|
||||
TRANSKRIPT & NUTZERANWEISUNG:
|
||||
## ALLGEMEINE RICHTLINIEN:
|
||||
- Entferne Redundanzen und Smalltalk
|
||||
- Keine Zeitstempel oder Sprecherangaben (wenn nicht gefordert)
|
||||
- Sachlich, präzise, professionell
|
||||
- Keine Spekulationen oder Meinungen (wenn nicht gefordert)
|
||||
|
||||
---
|
||||
|
||||
**NUTZERANWEISUNG:**
|
||||
[Hier kommt die Anforderung des Nutzers hin]
|
||||
|
||||
**TRANSKRIPT:**
|
||||
[Hier kommt das Meeting-Transkript hin]
|
||||
@@ -1,45 +1,61 @@
|
||||
# Follow-up Report Generator
|
||||
|
||||
Du bist ein professioneller Meeting-Analyst und Business Writer.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle einen strukturierten Follow-up Report basierend auf dem folgenden Meeting-Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
ANFORDERUNGEN:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle einen strukturierten Follow-up Report basierend auf dem Meeting-Transkript.
|
||||
|
||||
## 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
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR DES DOKUMENTS:
|
||||
1. Titel & Metadaten
|
||||
- Meetingtitel (ableiten)
|
||||
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben“)
|
||||
- Teilnehmer (zusammengefasst)
|
||||
## STRUKTUR DES DOKUMENTS:
|
||||
|
||||
2. Executive Summary (max. 5 Bullet Points)
|
||||
### 1. Titel & Metadaten
|
||||
- Meetingtitel (ableiten)
|
||||
- Datum (falls im Transkript erwähnt, sonst „nicht angegeben")
|
||||
- Teilnehmer (zusammengefasst)
|
||||
|
||||
3. Besprochene Themen
|
||||
- Thema
|
||||
- Kernaussagen
|
||||
- Relevante Erkenntnisse
|
||||
### 2. Executive Summary
|
||||
- Max. 5 Bullet Points
|
||||
- Kernpunkte zusammenfassen
|
||||
|
||||
4. Entscheidungen
|
||||
- Entscheidung
|
||||
- Kontext / Begründung
|
||||
### 3. Besprochene Themen
|
||||
- Thema
|
||||
- Kernaussagen
|
||||
- Relevante Erkenntnisse
|
||||
|
||||
5. Action Items
|
||||
- Aufgabe
|
||||
- Verantwortlich (falls ableitbar)
|
||||
- Ziel / Zweck
|
||||
### 4. Entscheidungen
|
||||
- Entscheidung
|
||||
- Kontext / Begründung
|
||||
|
||||
6. Offene Fragen & Risiken
|
||||
### 5. Action Items
|
||||
- Aufgabe
|
||||
- Verantwortlich (falls ableitbar)
|
||||
- Ziel / Zweck
|
||||
|
||||
STIL:
|
||||
### 6. Offene Fragen & Risiken
|
||||
|
||||
## STIL:
|
||||
- Überschriften klar strukturiert
|
||||
- Bullet Points bevorzugen
|
||||
- Präzise, keine Umgangssprache
|
||||
- Keine Zeitstempel oder Sprecherangaben
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,27 +1,54 @@
|
||||
# Result Protocol Generator
|
||||
|
||||
Du bist ein professioneller Protokollführer.
|
||||
|
||||
AUFGABE:
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle ein Ergebnisprotokoll basierend auf dem Meeting-Transkript.
|
||||
|
||||
FOKUS:
|
||||
## FOKUS:
|
||||
- Ergebnisse statt Diskussionen
|
||||
- Entscheidungen, Beschlüsse, Vereinbarungen
|
||||
- Klare, überprüfbare Aussagen
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
1. Meeting-Informationen
|
||||
2. Ergebnisse je Thema
|
||||
- Thema
|
||||
- Ergebnis / Beschluss
|
||||
3. Entscheidungen
|
||||
4. Aufgaben & Verantwortlichkeiten
|
||||
5. Offene Punkte
|
||||
## STRUKTUR:
|
||||
|
||||
REGELN:
|
||||
### 1. Meeting-Informationen
|
||||
- Titel
|
||||
- Datum
|
||||
- Teilnehmer
|
||||
|
||||
### 2. Ergebnisse je Thema
|
||||
- **Thema**
|
||||
- **Ergebnis / Beschluss**
|
||||
|
||||
### 3. Entscheidungen
|
||||
- Klare Entscheidungen mit Kontext
|
||||
|
||||
### 4. Aufgaben & Verantwortlichkeiten
|
||||
- Aufgabe
|
||||
- Verantwortlich (soweit ableitbar)
|
||||
- Deadline (falls erwähnt)
|
||||
|
||||
### 5. Offene Punkte
|
||||
- Ungelöste Fragen
|
||||
- Ausstehende Klärungen
|
||||
|
||||
## REGELN:
|
||||
- Keine Meinungen oder Spekulationen
|
||||
- Keine Zeit- oder Sprecherangaben
|
||||
- Sachlich, formal
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Fokus auf Fakten und Ergebnisse
|
||||
|
||||
---
|
||||
|
||||
TRANSKRIPT:
|
||||
**TRANSKRIPT:**
|
||||
@@ -1,35 +1,61 @@
|
||||
# Sprint Planning Note Generator
|
||||
|
||||
Du bist ein erfahrener Scrum Master.
|
||||
|
||||
AUFGABE:
|
||||
Erstelle Sprint Planning Notes aus dem folgenden Meeting-Transkript.
|
||||
## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN:
|
||||
**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.**
|
||||
- RICHTIG: "speakerA hat entschieden..."
|
||||
- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen
|
||||
|
||||
FOKUS:
|
||||
Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess.
|
||||
|
||||
---
|
||||
|
||||
## AUFGABE:
|
||||
Erstelle Sprint Planning Notes aus dem Meeting-Transkript.
|
||||
|
||||
## FOKUS:
|
||||
- Sprint-Ziele
|
||||
- User Stories / Tasks
|
||||
- Abhängigkeiten
|
||||
- Risiken
|
||||
- Commitments
|
||||
- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten
|
||||
|
||||
STRUKTUR:
|
||||
1. Sprint Overview
|
||||
- Sprint-Ziel
|
||||
- Zeitraum (falls erwähnt)
|
||||
## STRUKTUR:
|
||||
|
||||
2. Geplante Arbeit
|
||||
- User Story / Task
|
||||
- Beschreibung
|
||||
- Akzeptanzkriterien (falls ableitbar)
|
||||
### 1. Sprint Overview
|
||||
- **Sprint-Ziel:** (Kurz und prägnant)
|
||||
- **Zeitraum:** (Falls im Transkript erwähnt)
|
||||
|
||||
3. Abhängigkeiten & Blocker
|
||||
### 2. Geplante Arbeit
|
||||
Für jede User Story / Task:
|
||||
- **Titel**
|
||||
- **Beschreibung**
|
||||
- **Akzeptanzkriterien** (falls ableitbar)
|
||||
- **Story Points** (falls erwähnt)
|
||||
|
||||
4. Risiken & Annahmen
|
||||
### 3. Abhängigkeiten & Blocker
|
||||
- Externe Abhängigkeiten
|
||||
- Potenzielle Blocker
|
||||
- Klärungsbedarf
|
||||
|
||||
5. Vereinbarungen / Team-Commitments
|
||||
### 4. Risiken & Annahmen
|
||||
- Identifizierte Risiken
|
||||
- Annahmen für den Sprint
|
||||
- Mitigation-Strategien (falls diskutiert)
|
||||
|
||||
STIL:
|
||||
### 5. Team-Commitments / Vereinbarungen
|
||||
- Vereinbarte Commitments
|
||||
- Rollen und Verantwortlichkeiten
|
||||
- Definition of Done (falls diskutiert)
|
||||
|
||||
## STIL:
|
||||
- Agile-konform
|
||||
- Klar & umsetzungsorientiert
|
||||
- Bullet Points bevorzugen
|
||||
- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden
|
||||
- Keine Zeitstempel oder Sprecherangaben
|
||||
|
||||
TRANSKRIPT:
|
||||
---
|
||||
|
||||
**TRANSKRIPT:**
|
||||
Reference in New Issue
Block a user