diff --git a/src/components/sidebar/tabs/queue/ResultAudio.vue b/src/components/sidebar/tabs/queue/ResultAudio.vue
new file mode 100644
index 0000000000..60c70673a3
--- /dev/null
+++ b/src/components/sidebar/tabs/queue/ResultAudio.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/components/sidebar/tabs/queue/ResultGallery.vue b/src/components/sidebar/tabs/queue/ResultGallery.vue
index e60a91c74b..7309c901e5 100644
--- a/src/components/sidebar/tabs/queue/ResultGallery.vue
+++ b/src/components/sidebar/tabs/queue/ResultGallery.vue
@@ -35,6 +35,7 @@
class="galleria-image"
/>
+
@@ -46,6 +47,7 @@ import { onMounted, onUnmounted, ref, watch } from 'vue'
import ComfyImage from '@/components/common/ComfyImage.vue'
import { ResultItemImpl } from '@/stores/queueStore'
+import ResultAudio from './ResultAudio.vue'
import ResultVideo from './ResultVideo.vue'
const galleryVisible = ref(false)
diff --git a/src/components/sidebar/tabs/queue/ResultItem.vue b/src/components/sidebar/tabs/queue/ResultItem.vue
index 77c19ec1e4..9f05ab687b 100644
--- a/src/components/sidebar/tabs/queue/ResultItem.vue
+++ b/src/components/sidebar/tabs/queue/ResultItem.vue
@@ -12,6 +12,7 @@
:alt="result.filename"
/>
+
{{ result.mediaType }}
@@ -26,6 +27,7 @@ import ComfyImage from '@/components/common/ComfyImage.vue'
import { ResultItemImpl } from '@/stores/queueStore'
import { useSettingStore } from '@/stores/settingStore'
+import ResultAudio from './ResultAudio.vue'
import ResultVideo from './ResultVideo.vue'
const props = defineProps<{
diff --git a/src/locales/en/main.json b/src/locales/en/main.json
index e2fca8680b..76cdaab9fb 100644
--- a/src/locales/en/main.json
+++ b/src/locales/en/main.json
@@ -13,6 +13,7 @@
"terminal": "Terminal",
"logs": "Logs",
"videoFailedToLoad": "Video failed to load",
+ "audioFailedToLoad": "Audio failed to load",
"extensionName": "Extension Name",
"reloadToApplyChanges": "Reload to apply changes",
"insert": "Insert",
diff --git a/src/locales/es/main.json b/src/locales/es/main.json
index 71a150aa1a..bfefaa3291 100644
--- a/src/locales/es/main.json
+++ b/src/locales/es/main.json
@@ -248,6 +248,7 @@
"all": "Todo",
"amount": "Cantidad",
"apply": "Aplicar",
+ "audioFailedToLoad": "No se pudo cargar el audio",
"back": "Atrás",
"cancel": "Cancelar",
"capture": "captura",
diff --git a/src/locales/fr/main.json b/src/locales/fr/main.json
index 4cdc02b95b..52662f278c 100644
--- a/src/locales/fr/main.json
+++ b/src/locales/fr/main.json
@@ -248,6 +248,7 @@
"all": "Tout",
"amount": "Quantité",
"apply": "Appliquer",
+ "audioFailedToLoad": "Échec du chargement de l'audio",
"back": "Retour",
"cancel": "Annuler",
"capture": "capture",
diff --git a/src/locales/ja/main.json b/src/locales/ja/main.json
index 4824f5eb18..889a068d8d 100644
--- a/src/locales/ja/main.json
+++ b/src/locales/ja/main.json
@@ -248,6 +248,7 @@
"all": "すべて",
"amount": "量",
"apply": "適用する",
+ "audioFailedToLoad": "オーディオの読み込みに失敗しました",
"back": "戻る",
"cancel": "キャンセル",
"capture": "キャプチャ",
diff --git a/src/locales/ko/main.json b/src/locales/ko/main.json
index 72db448f0d..9f277c662d 100644
--- a/src/locales/ko/main.json
+++ b/src/locales/ko/main.json
@@ -248,6 +248,7 @@
"all": "모두",
"amount": "수량",
"apply": "적용",
+ "audioFailedToLoad": "오디오를 불러오지 못했습니다",
"back": "뒤로",
"cancel": "취소",
"capture": "캡처",
diff --git a/src/locales/ru/main.json b/src/locales/ru/main.json
index fda4a11a0d..10652401fa 100644
--- a/src/locales/ru/main.json
+++ b/src/locales/ru/main.json
@@ -248,6 +248,7 @@
"all": "Все",
"amount": "Количество",
"apply": "Применить",
+ "audioFailedToLoad": "Не удалось загрузить аудио",
"back": "Назад",
"cancel": "Отмена",
"capture": "захват",
diff --git a/src/locales/zh/main.json b/src/locales/zh/main.json
index 53504b9bf2..4d5e461f1a 100644
--- a/src/locales/zh/main.json
+++ b/src/locales/zh/main.json
@@ -248,6 +248,7 @@
"all": "全部",
"amount": "数量",
"apply": "应用",
+ "audioFailedToLoad": "音频加载失败",
"back": "返回",
"cancel": "取消",
"capture": "捕获",
diff --git a/src/stores/queueStore.ts b/src/stores/queueStore.ts
index e702a0f8eb..376063958d 100644
--- a/src/stores/queueStore.ts
+++ b/src/stores/queueStore.ts
@@ -106,6 +106,22 @@ export class ResultItemImpl {
return undefined
}
+ get htmlAudioType(): string | undefined {
+ if (this.isMp3) {
+ return 'audio/mpeg'
+ }
+ if (this.isWav) {
+ return 'audio/wav'
+ }
+ if (this.isOgg) {
+ return 'audio/ogg'
+ }
+ if (this.isFlac) {
+ return 'audio/flac'
+ }
+ return undefined
+ }
+
get isGif(): boolean {
return this.filename.endsWith('.gif')
}
@@ -130,21 +146,55 @@ export class ResultItemImpl {
return this.isGif || this.isWebp
}
+ get isMp3(): boolean {
+ return this.filename.endsWith('.mp3')
+ }
+
+ get isWav(): boolean {
+ return this.filename.endsWith('.wav')
+ }
+
+ get isOgg(): boolean {
+ return this.filename.endsWith('.ogg')
+ }
+
+ get isFlac(): boolean {
+ return this.filename.endsWith('.flac')
+ }
+
+ get isAudioBySuffix(): boolean {
+ return this.isMp3 || this.isWav || this.isOgg || this.isFlac
+ }
+
get isVideo(): boolean {
const isVideoByType =
this.mediaType === 'video' || !!this.format?.startsWith('video/')
- return this.isVideoBySuffix || (isVideoByType && !this.isImageBySuffix)
+ return (
+ this.isVideoBySuffix ||
+ (isVideoByType && !this.isImageBySuffix && !this.isAudioBySuffix)
+ )
}
get isImage(): boolean {
return (
this.isImageBySuffix ||
- (this.mediaType === 'images' && !this.isVideoBySuffix)
+ (this.mediaType === 'images' &&
+ !this.isVideoBySuffix &&
+ !this.isAudioBySuffix)
+ )
+ }
+
+ get isAudio(): boolean {
+ const isAudioByType =
+ this.mediaType === 'audio' || !!this.format?.startsWith('audio/')
+ return (
+ this.isAudioBySuffix ||
+ (isAudioByType && !this.isImageBySuffix && !this.isVideoBySuffix)
)
}
get supportsPreview(): boolean {
- return this.isImage || this.isVideo
+ return this.isImage || this.isVideo || this.isAudio
}
}
diff --git a/tests-ui/tests/store/queueStore.test.ts b/tests-ui/tests/store/queueStore.test.ts
index 7fd2f5bb6f..313673e693 100644
--- a/tests-ui/tests/store/queueStore.test.ts
+++ b/tests-ui/tests/store/queueStore.test.ts
@@ -115,4 +115,42 @@ describe('TaskItemImpl', () => {
expect(output.isVideo).toBe(true)
expect(output.isImage).toBe(false)
})
+
+ describe('audio format detection', () => {
+ const audioFormats = [
+ { extension: 'mp3', mimeType: 'audio/mpeg' },
+ { extension: 'wav', mimeType: 'audio/wav' },
+ { extension: 'ogg', mimeType: 'audio/ogg' },
+ { extension: 'flac', mimeType: 'audio/flac' }
+ ]
+
+ audioFormats.forEach(({ extension, mimeType }) => {
+ it(`should recognize ${extension} audio`, () => {
+ const taskItem = new TaskItemImpl(
+ 'History',
+ [0, 'prompt-id', {}, { client_id: 'client-id' }, []],
+ { status_str: 'success', messages: [], completed: true },
+ {
+ 'node-1': {
+ audio: [
+ {
+ filename: `test.${extension}`,
+ type: 'output',
+ subfolder: ''
+ }
+ ]
+ }
+ }
+ )
+
+ const output = taskItem.flatOutputs[0]
+
+ expect(output.htmlAudioType).toBe(mimeType)
+ expect(output.isAudio).toBe(true)
+ expect(output.isVideo).toBe(false)
+ expect(output.isImage).toBe(false)
+ expect(output.supportsPreview).toBe(true)
+ })
+ })
+ })
})