Vuenodes/audio widgets (#5627)

This pull request introduces a new audio playback widget for node UIs
and integrates it into the node widget system. The main changes include
the implementation of the `WidgetAudioUI` component, its registration in
the widget registry, and updates to pass node data to the new widget.
Additionally, some logging was added for debugging purposes.

**Audio Widget Implementation and Integration:**

* Added a new `WidgetAudioUI.vue` component that provides audio playback
controls (play/pause, progress slider, volume, options) and loads audio
files from the server based on node data.
* Registered the new `WidgetAudioUI` component in the widget registry by
importing it and adding an entry for the `audioUI` type.
[[1]](diffhunk://#diff-c2a60954f7fdf638716fa1f83e437774d5250e9c99f3aa83c84a1c0e9cc5769bR21)
[[2]](diffhunk://#diff-c2a60954f7fdf638716fa1f83e437774d5250e9c99f3aa83c84a1c0e9cc5769bR112-R115)
* Updated `NodeWidgets.vue` to pass `nodeInfo` as the `node-data` prop
to widgets of type `audioUI`, enabling the widget to access
node-specific audio file information.

**Debugging and Logging:**

* Added logging of `nodeData` in `LGraphNode.vue` and
`WidgetAudioUI.vue` to help with debugging and understanding the data
structure.
[[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R188-R189)
[[2]](diffhunk://#diff-71cce190d74c6b5359288857ab9917caededb8cdf1a7e6377578b78aa32be2fcR1-R284)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5627-Vuenodes-audio-widgets-2716d73d365081fbbc06c1e6cf4ebf4d)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Arjan Singh <1598641+arjansingh@users.noreply.github.com>
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
Co-authored-by: Robin Huang <robin.j.huang@gmail.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Johnpaul Chiwetelu
2025-10-10 05:29:06 +01:00
committed by GitHub
parent 4404c0461d
commit d7796fcda4
18 changed files with 1305 additions and 67 deletions

View File

@@ -11,7 +11,10 @@ import type {
IStringWidget
} from '@/lib/litegraph/src/types/widgets'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type { ResultItemType } from '@/schemas/apiSchema'
import {
getResourceURL,
splitFilePath
} from '@/renderer/extensions/vueNodes/widgets/utils/audioUtils'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import type { DOMWidget } from '@/scripts/domWidget'
import { useAudioService } from '@/services/audioService'
@@ -21,32 +24,6 @@ import { getNodeByLocatorId } from '@/utils/graphTraversalUtil'
import { api } from '../../scripts/api'
import { app } from '../../scripts/app'
function splitFilePath(path: string): [string, string] {
const folder_separator = path.lastIndexOf('/')
if (folder_separator === -1) {
return ['', path]
}
return [
path.substring(0, folder_separator),
path.substring(folder_separator + 1)
]
}
function getResourceURL(
subfolder: string,
filename: string,
type: ResultItemType = 'input'
): string {
const params = [
'filename=' + encodeURIComponent(filename),
'type=' + type,
'subfolder=' + subfolder,
app.getRandParam().substring(1)
].join('&')
return `/view?${params}`
}
async function uploadFile(
audioWidget: IStringWidget,
audioUIWidget: DOMWidget<HTMLAudioElement, string>,
@@ -123,7 +100,6 @@ app.registerExtension({
const audioUIWidget: DOMWidget<HTMLAudioElement, string> =
node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)
audioUIWidget.serialize = false
const { nodeData } = node.constructor
if (nodeData == null) throw new TypeError('nodeData is null')
@@ -199,6 +175,7 @@ app.registerExtension({
const audioUIWidget = node.widgets.find(
(w) => w.name === 'audioUI'
) as unknown as DOMWidget<HTMLAudioElement, string>
audioUIWidget.options.canvasOnly = true
const onAudioWidgetUpdate = () => {
audioUIWidget.element.src = api.apiURL(
@@ -273,9 +250,9 @@ app.registerExtension({
audio.controls = true
audio.classList.add('comfy-audio')
audio.setAttribute('name', 'media')
const audioUIWidget: DOMWidget<HTMLAudioElement, string> =
node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)
audioUIWidget.options.canvasOnly = true
let mediaRecorder: MediaRecorder | null = null
let isRecording = false