Aggiunta sezione per registrare in MP3 320 kbps da qualsiasi
dispositivo di input audio del sistema (mixer, scheda audio
esterna, microfono interno, BlackHole / driver virtuali per audio
di sistema).
- core/recorder.py: list_input_devices() parsa l'output di
ffmpeg -list_devices su AVFoundation (macOS) e DirectShow (Win),
marca come 'virtual' i driver loopback noti (BlackHole, Soundflower,
Loopback, VB-Cable, Stereo Mix, OBS). start_recording() lancia
ffmpeg in thread e emette eventi tick/started/stopped/error.
- api/bridge.py: list_audio_inputs, start_audio_recording,
stop_audio_recording, is_audio_recording
- webui: hero rosso, dropdown dispositivi con badge 'loopback',
selettore bitrate, timer HH:MM:SS animato, bottone REC con
pulse animation, card 'Ultima registrazione' con durata+path
- Hint visibile: per registrare audio di sistema serve BlackHole
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
WAV puo' contenere un blocco ID3v2 embedded oltre al PCM raw.
Mutagen.wave.WAVE espone gli stessi frame TIT2/TPE1/APIC etc.
del MP3.
- core/metadata.py: SUPPORTED_EXTS include '.wav', read/write via
WAVE.tags (con add_tags() se mancante)
- bridge.py: file picker include *.wav nel filter audio
Round-trip verificato: titolo/artista/album/anno/track/bpm/key/
commento + copertina preservati.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
I file filter di pywebview vogliono estensioni separate da ';' non
da spazio. Cambiato 'Audio (*.mp3 *.m4a ...)' in
'Audio (*.mp3;*.m4a;...)'. Stesso fix per il dialog copertine.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Nuova sezione 'Metadati' nella sidebar con editor completo dei tag:
titolo, artista, album, album artist, anno, traccia, genere, BPM,
key, commento, copertina.
- core/metadata.py: read/write metadati via mutagen, supporto ID3
(MP3), MP4 atoms (M4A/AAC) e Vorbis comments (FLAC)
- api/bridge.py: pick_audio_file, pick_image_file, read_metadata,
save_metadata. Cover passata come base64 al frontend per preview
- webui: hero ambra, form a griglia 2 colonne, anteprima cover 180x180,
bottoni cambia/rimuovi copertina, ricarica file
- requirements.txt: aggiunto mutagen>=1.47.0
- build_macos.py / build_windows.py: --collect-all mutagen
Modifiche correlate (in attesa di decisione utente sulla
distribuzione degli aggiornamenti):
- VERSION bumpato a v1.2.2 in core/config.py
- check_update ora interroga l'API GitHub Releases invece di
djluza.com/version.json (funzionera quando il repo sara pubblico)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Quando si carica un file .txt come tracklist, l'app ora scarica i
brani in <output_dir>/<nome_file>/ anziche direttamente in output_dir.
Es: 'Beatport Top 100 Melodic House & Techno.txt' -> cartella
'Beatport Top 100 Melodic House & Techno/' creata dentro la
cartella output predefinita.
- load_url_list ritorna 'name' (basename senza estensione)
- start_tracks_download accetta 'subfolder' opzionale e fa
os.path.join con sanitizzazione dei separatori
- JS passa state.loaded.name come subfolder
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adesso 'Carica lista' nella tab Scarica riconosce automaticamente
il formato del file .txt:
- Se la prima riga e un URL (http/https) -> URL list (come prima)
- Altrimenti -> tracklist parsata 'Artista - Titolo (variant) (durata)'
e scaricata cercando ogni brano su YouTube (riusa download_playlist)
Parser robusto: gestisce numerazione iniziale (1. / 1) / 1: / 1-),
qualsiasi tipo di dash (-, en-dash, em-dash, ...) e durata finale
'(M:SS)'. Testato sulla Beatport Top 100 Melodic House & Techno
(100/100 tracce parsate).
api/bridge.py: nuovo start_tracks_download, load_url_list ritorna
'kind: urls|tracks'.
webui/js/app.js: badge cambia tra 'X URL' e 'X tracce', avvio
chiama start_tracks_download quando appropriato.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- core/downloader.py: download_video() con format selector qualita
(best / 1080p / 720p / 480p), merge MP4, tracking .downloaded_videos
- api/bridge.py: start_video_download / stop_video_download / _video_worker.
Guard _any_job_running() per evitare concorrenza tra audio e video
(condividono lo stesso _stop_event)
- webui: nuova nav item, view con hero rosa (gradient pink->black),
selettore qualita, hint cookies per Instagram/Facebook privati
- CSS: palette pink, .hero-pink, .btn-pink, .progress-fill.pink,
componente .hint riusabile
- JS: handlers tab Video, canale bridge video:progress/video:done
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>