UI: show FFmpeg encoding progress in toaster
This commit is contained in:
parent
7dd8854ad1
commit
4d938b5478
2 changed files with 36 additions and 11 deletions
|
|
@ -1216,7 +1216,7 @@ export class LosslessAPI {
|
|||
if ((await getExtensionFromBlob(blob)) != 'flac') {
|
||||
blob = await ffmpeg(
|
||||
blob,
|
||||
{ args: ['-c:a', 'copy'] },
|
||||
{ args: ['-vn', '-map_metadata', '-1', '-map', '0:a', '-c:a', 'flac'] },
|
||||
'output.flac',
|
||||
'audio/flac',
|
||||
onProgress,
|
||||
|
|
|
|||
|
|
@ -195,11 +195,21 @@ export function updateDownloadProgress(trackId, progress) {
|
|||
const percent = progress.totalBytes ? Math.round((progress.receivedBytes / progress.totalBytes) * 100) : 0;
|
||||
|
||||
progressFill.style.width = `${percent}%`;
|
||||
progressFill.style.background = 'var(--highlight)';
|
||||
|
||||
const receivedMB = (progress.receivedBytes / (1024 * 1024)).toFixed(1);
|
||||
const totalMB = progress.totalBytes ? (progress.totalBytes / (1024 * 1024)).toFixed(1) : '?';
|
||||
|
||||
statusEl.textContent = `Downloading: ${receivedMB}MB / ${totalMB}MB (${percent}%)`;
|
||||
} else if (progress.stage === 'encoding') {
|
||||
const percent = progress.progress ? Math.round(progress.progress) : 0;
|
||||
progressFill.style.width = `${percent}%`;
|
||||
progressFill.style.background = '#3b82f6'; // Blue for encoding
|
||||
statusEl.textContent = `Converting: ${percent}%`;
|
||||
} else if (progress.stage === 'finalizing' || progress.stage === 'processing') {
|
||||
progressFill.style.width = '100%';
|
||||
progressFill.style.background = '#3b82f6';
|
||||
statusEl.textContent = progress.message || 'Processing...';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +278,7 @@ function removeBulkDownloadTask(notifEl) {
|
|||
}, 300);
|
||||
}
|
||||
|
||||
async function downloadTrackBlob(track, quality, api, lyricsManager = null, signal = null) {
|
||||
async function downloadTrackBlob(track, quality, api, lyricsManager = null, signal = null, onProgress = null) {
|
||||
let enrichedTrack = {
|
||||
...track,
|
||||
artist: track.artist || (track.artists && track.artists.length > 0 ? track.artists[0] : null),
|
||||
|
|
@ -343,7 +353,7 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign
|
|||
// Fallback
|
||||
if (downloadQuality !== 'LOSSLESS') {
|
||||
console.warn('Falling back to LOSSLESS (16-bit) download.');
|
||||
return downloadTrackBlob(track, 'LOSSLESS', api, lyricsManager, signal);
|
||||
return downloadTrackBlob(track, 'LOSSLESS', api, lyricsManager, signal, onProgress);
|
||||
}
|
||||
throw dashError;
|
||||
}
|
||||
|
|
@ -357,7 +367,7 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign
|
|||
|
||||
// Convert to MP3 320kbps if requested
|
||||
if (quality === 'MP3_320') {
|
||||
blob = await encodeToMp3(blob, () => undefined, signal);
|
||||
blob = await encodeToMp3(blob, onProgress || (() => undefined), signal);
|
||||
}
|
||||
|
||||
if (quality.endsWith('LOSSLESS')) {
|
||||
|
|
@ -367,10 +377,10 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign
|
|||
if ((await getExtensionFromBlob(blob)) != 'flac') {
|
||||
blob = await ffmpeg(
|
||||
blob,
|
||||
{ args: ['-c:a', 'copy'] },
|
||||
{ args: ['-vn', '-map_metadata', '-1', '-map', '0:a', '-c:a', 'flac'] },
|
||||
'output.flac',
|
||||
'audio/flac',
|
||||
() => undefined,
|
||||
onProgress,
|
||||
signal
|
||||
);
|
||||
}
|
||||
|
|
@ -381,7 +391,7 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign
|
|||
{ args: ['-c:a', 'alac'] },
|
||||
'output.m4a',
|
||||
'audio/mp4',
|
||||
() => undefined,
|
||||
onProgress,
|
||||
signal
|
||||
);
|
||||
break;
|
||||
|
|
@ -556,7 +566,9 @@ async function bulkDownloadToZipStream(
|
|||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle);
|
||||
|
||||
try {
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal);
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal, (p) => {
|
||||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle, p);
|
||||
});
|
||||
const filename = buildTrackFilename(track, quality, extension);
|
||||
const discNumber = discLayout.resolveDiscNumber(i);
|
||||
yield {
|
||||
|
|
@ -698,7 +710,9 @@ async function bulkDownloadToZipBlob(
|
|||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle);
|
||||
|
||||
try {
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal);
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal, (p) => {
|
||||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle, p);
|
||||
});
|
||||
const filename = buildTrackFilename(track, quality, extension);
|
||||
const discNumber = discLayout.resolveDiscNumber(i);
|
||||
yield {
|
||||
|
|
@ -841,7 +855,9 @@ async function bulkDownloadToZipNeutralino(
|
|||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle);
|
||||
|
||||
try {
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal);
|
||||
const { blob, extension } = await downloadTrackBlob(track, quality, api, null, signal, (p) => {
|
||||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle, p);
|
||||
});
|
||||
const filename = buildTrackFilename(track, quality, extension);
|
||||
const discNumber = discLayout.resolveDiscNumber(i);
|
||||
yield {
|
||||
|
|
@ -1303,12 +1319,21 @@ function createBulkDownloadNotification(type, name, _totalItems) {
|
|||
return notifEl;
|
||||
}
|
||||
|
||||
function updateBulkDownloadProgress(notifEl, current, total, currentItem) {
|
||||
function updateBulkDownloadProgress(notifEl, current, total, currentItem, ffmpegProgress = null) {
|
||||
const progressFill = notifEl.querySelector('.download-progress-fill');
|
||||
const statusEl = notifEl.querySelector('.download-status');
|
||||
|
||||
if (ffmpegProgress && (ffmpegProgress.stage === 'encoding' || ffmpegProgress.stage === 'finalizing')) {
|
||||
const percent = ffmpegProgress.progress ? Math.round(ffmpegProgress.progress) : 100;
|
||||
progressFill.style.width = `${percent}%`;
|
||||
progressFill.style.background = '#3b82f6'; // Blue for encoding
|
||||
statusEl.textContent = `Converting ${current}/${total}: ${percent}%`;
|
||||
return;
|
||||
}
|
||||
|
||||
const percent = total > 0 ? Math.round((current / total) * 100) : 0;
|
||||
progressFill.style.width = `${percent}%`;
|
||||
progressFill.style.background = 'var(--highlight)';
|
||||
statusEl.textContent = `${current}/${total} - ${currentItem}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue