mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 10:59:53 +00:00
[fix] Enable AUDIO_RECORD widget in both LiteGraph and Vue nodes modes (#6094)
Fixed the AUDIO_RECORD widget to display correctly in both rendering modes: - Removed conflicting AUDIO_RECORD registration from ComfyWidgets that was blocking the custom widget implementation in uploadAudio.ts extension - Changed canvasOnly flags from true to false on both audioUIWidget and recordWidget to enable Vue nodes rendering - Added type override (recordWidget.type = 'audiorecord') after widget creation to enable Vue component lookup while preserving LiteGraph button rendering - Removed unused IAudioRecordWidget type definition The widget now works correctly: - LiteGraph mode: Displays as a functional button - Vue nodes mode: Displays full recording UI with waveform visualization ## Summary <!-- One sentence describing what changed and why. --> ## Changes - **What**: <!-- Core functionality added/modified --> - **Breaking**: <!-- Any breaking changes (if none, remove this line) --> - **Dependencies**: <!-- New dependencies (if none, remove this line) --> ## Review Focus <!-- Critical design decisions or edge cases that need attention --> <!-- If this PR fixes an issue, uncomment and update the line below --> <!-- Fixes #ISSUE_NUMBER --> ## Screenshots (if applicable) <!-- Add screenshots or video recording to help explain your changes --> https://github.com/user-attachments/assets/cf6513d4-0a4b-4210-88e2-a948855b5206 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6094-fix-Enable-AUDIO_RECORD-widget-in-both-LiteGraph-and-Vue-nodes-modes-28e6d73d365081faa879f53e3e2dddad) by [Unito](https://www.unito.io) --------- Co-authored-by: bymyself <cbyrne@comfy.org>
This commit is contained in:
committed by
GitHub
parent
598d170d10
commit
9ef6f94f92
28
browser_tests/tests/recordAudio.spec.ts
Normal file
28
browser_tests/tests/recordAudio.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.beforeEach(async ({ comfyPage }) => {
|
||||
await comfyPage.setSetting('Comfy.UseNewMenu', 'Disabled')
|
||||
})
|
||||
|
||||
test.describe('Record Audio Node', () => {
|
||||
test('should add a record audio node and take a screenshot', async ({
|
||||
comfyPage
|
||||
}) => {
|
||||
// Open the search box by double clicking on the canvas
|
||||
await comfyPage.doubleClickCanvas()
|
||||
await expect(comfyPage.searchBox.input).toHaveCount(1)
|
||||
|
||||
// Search for and add the RecordAudio node
|
||||
await comfyPage.searchBox.fillAndSelectFirstNode('RecordAudio')
|
||||
await comfyPage.nextFrame()
|
||||
|
||||
// Verify the RecordAudio node was added
|
||||
const recordAudioNodes = await comfyPage.getNodeRefsByType('RecordAudio')
|
||||
expect(recordAudioNodes.length).toBe(1)
|
||||
|
||||
// Take a screenshot of the canvas with the RecordAudio node
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('record_audio_node.png')
|
||||
})
|
||||
})
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
@@ -253,7 +253,7 @@ app.registerExtension({
|
||||
audio.setAttribute('name', 'media')
|
||||
const audioUIWidget: DOMWidget<HTMLAudioElement, string> =
|
||||
node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)
|
||||
audioUIWidget.options.canvasOnly = true
|
||||
audioUIWidget.options.canvasOnly = false
|
||||
|
||||
let mediaRecorder: MediaRecorder | null = null
|
||||
let isRecording = false
|
||||
@@ -376,10 +376,12 @@ app.registerExtension({
|
||||
mediaRecorder.stop()
|
||||
}
|
||||
},
|
||||
{ serialize: false, canvasOnly: true }
|
||||
{ serialize: false, canvasOnly: false }
|
||||
)
|
||||
|
||||
recordWidget.label = t('g.startRecording')
|
||||
// Override the type for Vue rendering while keeping 'button' for LiteGraph
|
||||
recordWidget.type = 'audiorecord'
|
||||
|
||||
const originalOnRemoved = node.onRemoved
|
||||
node.onRemoved = function () {
|
||||
|
||||
@@ -79,7 +79,6 @@ export type IWidget =
|
||||
| ISelectButtonWidget
|
||||
| ITextareaWidget
|
||||
| IAssetWidget
|
||||
| IAudioRecordWidget
|
||||
|
||||
export interface IBooleanWidget extends IBaseWidget<boolean, 'toggle'> {
|
||||
type: 'toggle'
|
||||
@@ -228,11 +227,6 @@ export interface ITextareaWidget extends IBaseWidget<string, 'textarea'> {
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface IAudioRecordWidget extends IBaseWidget<string, 'audiorecord'> {
|
||||
type: 'audiorecord'
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface IAssetWidget
|
||||
extends IBaseWidget<string, 'asset', IWidgetOptions<string[]>> {
|
||||
type: 'asset'
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import type { IAudioRecordWidget } from '@/lib/litegraph/src/types/widgets'
|
||||
import type {
|
||||
AudioRecordInputSpec,
|
||||
InputSpec as InputSpecV2
|
||||
} from '@/schemas/nodeDef/nodeDefSchemaV2'
|
||||
import type { ComfyWidgetConstructorV2 } from '@/scripts/widgets'
|
||||
|
||||
export const useAudioRecordWidget = (): ComfyWidgetConstructorV2 => {
|
||||
return (node: LGraphNode, inputSpec: InputSpecV2): IAudioRecordWidget => {
|
||||
const {
|
||||
name,
|
||||
default: defaultValue = '',
|
||||
options = {}
|
||||
} = inputSpec as AudioRecordInputSpec
|
||||
|
||||
const widget = node.addWidget('audiorecord', name, defaultValue, () => {}, {
|
||||
serialize: true,
|
||||
...options
|
||||
}) as IAudioRecordWidget
|
||||
|
||||
return widget
|
||||
}
|
||||
}
|
||||
@@ -152,13 +152,6 @@ const zTextareaInputSpec = zBaseInputOptions.extend({
|
||||
.optional()
|
||||
})
|
||||
|
||||
const zAudioRecordInputSpec = zBaseInputOptions.extend({
|
||||
type: z.literal('AUDIORECORD'),
|
||||
name: z.string(),
|
||||
isOptional: z.boolean().optional(),
|
||||
options: z.record(z.unknown()).optional()
|
||||
})
|
||||
|
||||
const zCustomInputSpec = zBaseInputOptions.extend({
|
||||
type: z.string(),
|
||||
name: z.string(),
|
||||
@@ -174,7 +167,6 @@ const zInputSpec = z.union([
|
||||
zColorInputSpec,
|
||||
zFileUploadInputSpec,
|
||||
zImageInputSpec,
|
||||
zAudioRecordInputSpec,
|
||||
zImageCompareInputSpec,
|
||||
zMarkdownInputSpec,
|
||||
zTreeSelectInputSpec,
|
||||
@@ -230,7 +222,6 @@ export type GalleriaInputSpec = z.infer<typeof zGalleriaInputSpec>
|
||||
export type SelectButtonInputSpec = z.infer<typeof zSelectButtonInputSpec>
|
||||
export type TextareaInputSpec = z.infer<typeof zTextareaInputSpec>
|
||||
export type CustomInputSpec = z.infer<typeof zCustomInputSpec>
|
||||
export type AudioRecordInputSpec = z.infer<typeof zAudioRecordInputSpec>
|
||||
|
||||
export type InputSpec = z.infer<typeof zInputSpec>
|
||||
export type OutputSpec = z.infer<typeof zOutputSpec>
|
||||
|
||||
@@ -6,7 +6,6 @@ import type {
|
||||
IStringWidget
|
||||
} from '@/lib/litegraph/src/types/widgets'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useAudioRecordWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useAudioRecordWidget'
|
||||
import { useBooleanWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useBooleanWidget'
|
||||
import { useChartWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useChartWidget'
|
||||
import { useColorWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useColorWidget'
|
||||
@@ -305,6 +304,5 @@ export const ComfyWidgets: Record<string, ComfyWidgetConstructor> = {
|
||||
CHART: transformWidgetConstructorV2ToV1(useChartWidget()),
|
||||
GALLERIA: transformWidgetConstructorV2ToV1(useGalleriaWidget()),
|
||||
SELECTBUTTON: transformWidgetConstructorV2ToV1(useSelectButtonWidget()),
|
||||
TEXTAREA: transformWidgetConstructorV2ToV1(useTextareaWidget()),
|
||||
AUDIO_RECORD: transformWidgetConstructorV2ToV1(useAudioRecordWidget())
|
||||
TEXTAREA: transformWidgetConstructorV2ToV1(useTextareaWidget())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user