Fix multiple issues: format API, Gradio availability, storage, UI responsiveness
- Format endpoint now calls ACE-Step /format_input REST API directly instead of spawning Python, fixing ENOENT errors on Windows (#44, #27, #34) - isGradioAvailable() tries /gradio_api/info, /info, / in sequence to handle Gradio 4.x/5.x/6.x version differences, fixing generation fallback (#53, #20) - Storage getUrl/getPublicUrl normalize /audio/ prefix to prevent double-prefix URLs when reference tracks are used for cover generation (#10) - Gradio args: fix normalization_db default from 0.0 to -1.0 (Gradio default) - Volume popover: add 400ms delay before hiding to prevent accidental dismissal (#51) - Polling: skip setSongs state update when nothing changed to reduce re-renders (#51) - FFmpeg: add jsdelivr CDN fallback when unpkg fails (#30) - Model switching: add switchModelIfNeeded() via /v1/init REST API (#45)
This commit is contained in:
@@ -69,6 +69,7 @@ export const Player: React.FC<PlayerProps> = ({
|
||||
const progressBarRef = useRef<HTMLDivElement>(null);
|
||||
const fullscreenProgressRef = useRef<HTMLDivElement>(null);
|
||||
const [isHoveringVolume, setIsHoveringVolume] = useState(false);
|
||||
const volumeHideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
const [shareModalOpen, setShareModalOpen] = useState(false);
|
||||
@@ -755,8 +756,13 @@ export const Player: React.FC<PlayerProps> = ({
|
||||
{/* Volume Control with Vertical Slider */}
|
||||
<div
|
||||
className="relative group hidden md:block"
|
||||
onMouseEnter={() => setIsHoveringVolume(true)}
|
||||
onMouseLeave={() => setIsHoveringVolume(false)}
|
||||
onMouseEnter={() => {
|
||||
if (volumeHideTimer.current) clearTimeout(volumeHideTimer.current);
|
||||
setIsHoveringVolume(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
volumeHideTimer.current = setTimeout(() => setIsHoveringVolume(false), 400);
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => onVolumeChange(volume === 0 ? 0.8 : 0)}
|
||||
|
||||
@@ -228,17 +228,30 @@ export const VideoGeneratorModal: React.FC<VideoGeneratorModalProps> = ({ isOpen
|
||||
}
|
||||
});
|
||||
|
||||
const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/esm';
|
||||
await ffmpeg.load({
|
||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
|
||||
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
|
||||
});
|
||||
const cdnBases = [
|
||||
'https://unpkg.com/@ffmpeg/core@0.12.6/dist/esm',
|
||||
'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.6/dist/esm',
|
||||
];
|
||||
let loaded = false;
|
||||
for (const baseURL of cdnBases) {
|
||||
try {
|
||||
await ffmpeg.load({
|
||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
|
||||
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
|
||||
});
|
||||
loaded = true;
|
||||
break;
|
||||
} catch {
|
||||
console.warn(`FFmpeg load failed from ${baseURL}, trying next CDN...`);
|
||||
}
|
||||
}
|
||||
if (!loaded) throw new Error('All CDN sources failed');
|
||||
|
||||
ffmpegRef.current = ffmpeg;
|
||||
setFfmpegLoaded(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to load FFmpeg:', error);
|
||||
alert('Failed to load video encoder. Please refresh and try again.');
|
||||
alert('Failed to load video encoder. Check your internet connection and try again.');
|
||||
} finally {
|
||||
setFfmpegLoading(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user