Files
tueit_Transkriptor/frontend/settings.js
T
thomas.kopp a37e09fb4e feat: copy transcript to Obsidian vault on open
Config: obsidian.vault path. On Obsidian button click, file is copied to
vault dir then opened via obsidian:// URI. Vault path configurable in settings.
2026-04-02 11:00:55 +02:00

124 lines
4.9 KiB
JavaScript

const token = sessionStorage.getItem('token');
function authHeaders() {
return token ? { 'Authorization': 'Bearer ' + token } : {};
}
function apiFetch(url, options) {
options = options || {};
return fetch(url, Object.assign({}, options, {
headers: Object.assign({'Content-Type': 'application/json'}, authHeaders(), options.headers || {}),
}));
}
let _devices = [];
function showToast(msg) {
const t = document.getElementById('toast');
t.textContent = msg;
t.classList.add('show');
setTimeout(function() { t.classList.remove('show'); }, 2500);
}
async function loadDevices() {
const r = await apiFetch('/audio/devices');
if (!r.ok) return;
_devices = await r.json();
const sel = document.getElementById('audio-device');
const current = sel.value;
sel.replaceChildren(new Option('Systemstandard', ''));
_devices.forEach(function(d) { sel.appendChild(new Option(d.name, d.name)); });
if (current) sel.value = current;
['combined-mic', 'combined-monitor'].forEach(function(id) {
const el = document.getElementById(id);
el.replaceChildren();
_devices.forEach(function(d) { el.appendChild(new Option(d.name, d.name)); });
});
}
async function loadOllamaModels(baseUrl, current) {
try {
const parsed = new URL(baseUrl);
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return;
const r = await fetch(parsed.origin + '/api/tags');
if (!r.ok) return;
const data = await r.json();
const sel = document.getElementById('ollama-model');
sel.replaceChildren();
(data.models || []).forEach(function(m) { sel.appendChild(new Option(m.name, m.name)); });
if (current) sel.value = current;
} catch(e) {}
}
async function loadConfig() {
const r = await apiFetch('/config');
if (!r.ok) return;
const cfg = await r.json();
document.getElementById('audio-device').value = (cfg.audio && cfg.audio.device) || '';
document.getElementById('whisper-backend').value = (cfg.whisper && cfg.whisper.backend) || 'openai';
document.getElementById('whisper-url').value = (cfg.whisper && cfg.whisper.base_url) || '';
document.getElementById('whisper-model').value = (cfg.whisper && cfg.whisper.model) || 'large-v3';
const ollamaUrl = (cfg.ollama && cfg.ollama.base_url) || 'http://localhost:11434';
document.getElementById('ollama-url').value = ollamaUrl;
await loadOllamaModels(ollamaUrl, cfg.ollama && cfg.ollama.model);
const diarCfg = cfg.diarization || {};
document.getElementById('diar-enabled').checked = !!diarCfg.enabled;
document.getElementById('diar-hf-token').value = diarCfg.hf_token || '';
document.getElementById('obsidian-vault').value = (cfg.obsidian && cfg.obsidian.vault) || '';
}
document.getElementById('refresh-devices-btn').addEventListener('click', loadDevices);
document.getElementById('create-combined-btn').addEventListener('click', function() {
document.getElementById('combined-form').classList.toggle('visible');
});
document.getElementById('combined-cancel-btn').addEventListener('click', function() {
document.getElementById('combined-form').classList.remove('visible');
});
document.getElementById('combined-confirm-btn').addEventListener('click', async function() {
const mic = document.getElementById('combined-mic').value;
const monitor = document.getElementById('combined-monitor').value;
const r = await apiFetch('/audio/combined', {
method: 'POST',
body: JSON.stringify({ mic: mic, monitor: monitor }),
});
if (!r.ok) { showToast('Fehler beim Erstellen'); return; }
const data = await r.json();
showToast('Erstellt: ' + data.device);
document.getElementById('combined-form').classList.remove('visible');
await loadDevices();
document.getElementById('audio-device').value = data.device;
});
document.getElementById('ollama-url').addEventListener('change', function(e) {
loadOllamaModels(e.target.value, document.getElementById('ollama-model').value);
});
document.getElementById('save-btn').addEventListener('click', async function() {
const body = {
audio: { device: document.getElementById('audio-device').value },
whisper: {
base_url: document.getElementById('whisper-url').value,
model: document.getElementById('whisper-model').value,
backend: document.getElementById('whisper-backend').value,
},
ollama: {
base_url: document.getElementById('ollama-url').value,
model: document.getElementById('ollama-model').value,
},
obsidian: {
vault: document.getElementById('obsidian-vault').value.trim(),
},
diarization: {
enabled: document.getElementById('diar-enabled').checked,
hf_token: document.getElementById('diar-hf-token').value.trim(),
},
};
const r = await apiFetch('/config', { method: 'PUT', body: JSON.stringify(body) });
if (r.ok) { showToast('Gespeichert'); } else { showToast('Fehler beim Speichern'); }
});
(async function() {
if (!token) { location.href = '/login'; return; }
await loadDevices();
await loadConfig();
})();