Browse Source

feat: rename Audio Input to Audio, add audio input handle for pass-through

- Rename node title from "Audio Input" to "Audio"
- Rename label in ConnectionDropMenu from "Audio Input" to "Audio"
- Add target (input) handle to Audio node so it can receive audio from
  GenerateAudio and other upstream nodes
- Add Audio node to AUDIO_TARGET_OPTIONS so it appears in the context
  menu when dragging from GenerateAudio's output connector
- Add execution logic: connected audio populates audioFile (connection
  wins over uploaded file), enabling pass-through to downstream nodes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
f0e41a8f51
  1. 11
      src/components/ConnectionDropMenu.tsx
  2. 3
      src/components/WorkflowCanvas.tsx
  3. 9
      src/components/nodes/AudioInputNode.tsx
  4. 11
      src/store/execution/executeNode.ts
  5. 11
      src/store/workflowStore.ts

11
src/components/ConnectionDropMenu.tsx

@ -290,6 +290,15 @@ const VIDEO_SOURCE_OPTIONS: MenuOption[] = [
// Audio target options (nodes that accept audio input)
const AUDIO_TARGET_OPTIONS: MenuOption[] = [
{
type: "audioInput",
label: "Audio",
icon: (
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 9l10.5-3m0 6.553v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 11-.99-3.467l2.31-.66a2.25 2.25 0 001.632-2.163zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 01-.99-3.467l2.31-.66A2.25 2.25 0 009 15.553z" />
</svg>
),
},
{
type: "output",
label: "Output",
@ -314,7 +323,7 @@ const AUDIO_TARGET_OPTIONS: MenuOption[] = [
const AUDIO_SOURCE_OPTIONS: MenuOption[] = [
{
type: "audioInput",
label: "Audio Input",
label: "Audio",
icon: (
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 9l10.5-3m0 6.553v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 11-.99-3.467l2.31-.66a2.25 2.25 0 001.632-2.163zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 01-.99-3.467l2.31-.66A2.25 2.25 0 009 15.553z" />

3
src/components/WorkflowCanvas.tsx

@ -850,7 +850,8 @@ export function WorkflowCanvas() {
}
} else if (handleType === "audio") {
if (nodeType === "audioInput") {
// AudioInput outputs audio
// Audio node: accepts audio input and outputs audio
targetHandleId = "audio";
sourceHandleIdForNewNode = "audio";
} else if (nodeType === "generateAudio") {
// GenerateAudio outputs audio

9
src/components/nodes/AudioInputNode.tsx

@ -278,7 +278,7 @@ export function AudioInputNode({ id, data, selected }: NodeProps<AudioInputNodeT
return (
<BaseNode
id={id}
title="Audio Input"
title="Audio"
customTitle={nodeData.customTitle}
comment={nodeData.comment}
onCustomTitleChange={(title) => updateNodeData(id, { customTitle: title || undefined })}
@ -389,6 +389,13 @@ export function AudioInputNode({ id, data, selected }: NodeProps<AudioInputNodeT
</div>
)}
<Handle
type="target"
position={Position.Left}
id="audio"
data-handletype="audio"
style={{ background: "rgb(167, 139, 250)" }}
/>
<Handle
type="source"
position={Position.Right}

11
src/store/execution/executeNode.ts

@ -41,9 +41,16 @@ export async function executeNode(
switch (ctx.node.type) {
case "imageInput":
case "audioInput":
// Data source nodes — no execution needed
// Data source node — no execution needed
break;
case "audioInput": {
// If audio is connected from upstream, use it (connection wins over upload)
const audioInputs = ctx.getConnectedInputs(ctx.node.id);
if (audioInputs.audio.length > 0 && audioInputs.audio[0]) {
ctx.updateNodeData(ctx.node.id, { audioFile: audioInputs.audio[0] });
}
break;
}
case "annotation":
await executeAnnotation(ctx);
break;

11
src/store/workflowStore.ts

@ -870,9 +870,16 @@ export const useWorkflowStore = create<WorkflowStore>((set, get) => ({
switch (node.type) {
case "imageInput":
case "audioInput":
// Data source nodes - no execution needed
// Data source node - no execution needed
break;
case "audioInput": {
// If audio is connected from upstream, use it (connection wins over upload)
const audioInputs = get().getConnectedInputs(node.id);
if (audioInputs.audio.length > 0 && audioInputs.audio[0]) {
get().updateNodeData(node.id, { audioFile: audioInputs.audio[0] });
}
break;
}
case "glbViewer":
await executeGlbViewer(executionCtx);
break;

Loading…
Cancel
Save