fix(02): Alpine libmpv/libsndfile symlinks, upload endpoint, browser file picker
- Dockerfile: add libmpv.so + libsndfile.so symlinks (Alpine/musl has no ldconfig) - engine.py: monkey-patch ctypes.util.find_library as fallback for Alpine - audio.py: add /upload (multipart) and /files endpoints - pyproject.toml: add python-multipart - frontend: replace path input with upload button + file selector dropdown
This commit is contained in:
@@ -224,10 +224,55 @@ if (seekBar) {
|
||||
});
|
||||
}
|
||||
|
||||
// Load audio button
|
||||
// Populate file selector
|
||||
async function refreshFileList(selectValue) {
|
||||
const sel = document.getElementById('audio-select');
|
||||
if (!sel) return;
|
||||
try {
|
||||
const res = await fetch('/api/audio/files');
|
||||
if (!res.ok) return;
|
||||
const { files } = await res.json();
|
||||
const prev = selectValue ?? sel.value;
|
||||
sel.innerHTML = '<option value="">— select file —</option>';
|
||||
files.forEach(name => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = `/app/shows/${name}`;
|
||||
opt.textContent = name;
|
||||
if (opt.value === prev) opt.selected = true;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[audio] file list error:', e);
|
||||
}
|
||||
}
|
||||
refreshFileList();
|
||||
|
||||
// Upload audio file
|
||||
document.getElementById('audio-upload')?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
try {
|
||||
const res = await fetch('/api/audio/upload', { method: 'POST', body: form });
|
||||
if (!res.ok) {
|
||||
const err = await res.json();
|
||||
console.error('[audio] upload failed:', err.detail);
|
||||
return;
|
||||
}
|
||||
const { path } = await res.json();
|
||||
await refreshFileList(path);
|
||||
setTimeout(loadWaveform, 500);
|
||||
} catch (err) {
|
||||
console.error('[audio] upload error:', err);
|
||||
}
|
||||
e.target.value = '';
|
||||
});
|
||||
|
||||
// Load selected audio file
|
||||
document.getElementById('btn-load')?.addEventListener('click', async () => {
|
||||
const pathInput = document.getElementById('audio-path');
|
||||
const path = pathInput?.value.trim();
|
||||
const sel = document.getElementById('audio-select');
|
||||
const path = sel?.value;
|
||||
if (!path) return;
|
||||
try {
|
||||
const res = await fetch('/api/audio/load', {
|
||||
@@ -240,7 +285,6 @@ document.getElementById('btn-load')?.addEventListener('click', async () => {
|
||||
console.error('[audio] load failed:', err.detail);
|
||||
return;
|
||||
}
|
||||
// Wait briefly for mpv to initialize, then fetch waveform
|
||||
setTimeout(loadWaveform, 500);
|
||||
} catch (err) {
|
||||
console.error('[audio] load error:', err);
|
||||
|
||||
Reference in New Issue
Block a user