mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Update voice debug for new API (#15913)
* Update voice debug for new API * Update imports * Remove wrong key * Some HTML formatting
This commit is contained in:
parent
74cfccaac7
commit
d9dbb69e62
17
src/data/stt.ts
Normal file
17
src/data/stt.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export interface SpeechMetadata {
|
||||||
|
language: string;
|
||||||
|
format: "wav" | "ogg";
|
||||||
|
codec: "pcm" | "opus";
|
||||||
|
bit_rate: 8 | 16 | 24 | 32;
|
||||||
|
sample_rate:
|
||||||
|
| 8000
|
||||||
|
| 11000
|
||||||
|
| 16000
|
||||||
|
| 18900
|
||||||
|
| 22000
|
||||||
|
| 32000
|
||||||
|
| 37800
|
||||||
|
| 44100
|
||||||
|
| 48000;
|
||||||
|
channel: 1 | 2;
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { ConversationResult } from "./conversation";
|
import type { ConversationResult } from "./conversation";
|
||||||
|
import type { ResolvedMediaSource } from "./media_source";
|
||||||
|
import type { SpeechMetadata } from "./stt";
|
||||||
|
|
||||||
interface PipelineEventBase {
|
interface PipelineEventBase {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@ -12,8 +14,8 @@ interface PipelineRunStartEvent extends PipelineEventBase {
|
|||||||
language: string;
|
language: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
interface PipelineRunFinishEvent extends PipelineEventBase {
|
interface PipelineRunEndEvent extends PipelineEventBase {
|
||||||
type: "run-finish";
|
type: "run-end";
|
||||||
data: Record<string, never>;
|
data: Record<string, never>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,11 +29,16 @@ interface PipelineErrorEvent extends PipelineEventBase {
|
|||||||
|
|
||||||
interface PipelineSTTStartEvent extends PipelineEventBase {
|
interface PipelineSTTStartEvent extends PipelineEventBase {
|
||||||
type: "stt-start";
|
type: "stt-start";
|
||||||
data: Record<string, never>;
|
data: {
|
||||||
|
engine: string;
|
||||||
|
metadata: SpeechMetadata;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
interface PipelineSTTFinishEvent extends PipelineEventBase {
|
interface PipelineSTTEndEvent extends PipelineEventBase {
|
||||||
type: "stt-finish";
|
type: "stt-end";
|
||||||
data: Record<string, never>;
|
data: {
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PipelineIntentStartEvent extends PipelineEventBase {
|
interface PipelineIntentStartEvent extends PipelineEventBase {
|
||||||
@ -41,8 +48,8 @@ interface PipelineIntentStartEvent extends PipelineEventBase {
|
|||||||
intent_input: string;
|
intent_input: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
interface PipelineIntentFinishEvent extends PipelineEventBase {
|
interface PipelineIntentEndEvent extends PipelineEventBase {
|
||||||
type: "intent-finish";
|
type: "intent-end";
|
||||||
data: {
|
data: {
|
||||||
intent_output: ConversationResult;
|
intent_output: ConversationResult;
|
||||||
};
|
};
|
||||||
@ -50,27 +57,35 @@ interface PipelineIntentFinishEvent extends PipelineEventBase {
|
|||||||
|
|
||||||
interface PipelineTTSStartEvent extends PipelineEventBase {
|
interface PipelineTTSStartEvent extends PipelineEventBase {
|
||||||
type: "tts-start";
|
type: "tts-start";
|
||||||
data: Record<string, never>;
|
data: {
|
||||||
|
engine: string;
|
||||||
|
tts_input: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
interface PipelineTTSFinishEvent extends PipelineEventBase {
|
interface PipelineTTSEndEvent extends PipelineEventBase {
|
||||||
type: "tts-finish";
|
type: "tts-end";
|
||||||
data: Record<string, never>;
|
data: {
|
||||||
|
tts_output: ResolvedMediaSource;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type PipelineRunEvent =
|
type PipelineRunEvent =
|
||||||
| PipelineRunStartEvent
|
| PipelineRunStartEvent
|
||||||
| PipelineRunFinishEvent
|
| PipelineRunEndEvent
|
||||||
| PipelineErrorEvent
|
| PipelineErrorEvent
|
||||||
| PipelineSTTStartEvent
|
| PipelineSTTStartEvent
|
||||||
| PipelineSTTFinishEvent
|
| PipelineSTTEndEvent
|
||||||
| PipelineIntentStartEvent
|
| PipelineIntentStartEvent
|
||||||
| PipelineIntentFinishEvent
|
| PipelineIntentEndEvent
|
||||||
| PipelineTTSStartEvent
|
| PipelineTTSStartEvent
|
||||||
| PipelineTTSFinishEvent;
|
| PipelineTTSEndEvent;
|
||||||
|
|
||||||
interface PipelineRunOptions {
|
interface PipelineRunOptions {
|
||||||
|
start_stage: "stt" | "intent" | "tts";
|
||||||
|
end_stage: "stt" | "intent" | "tts";
|
||||||
|
language?: string;
|
||||||
pipeline?: string;
|
pipeline?: string;
|
||||||
intent_input?: string;
|
input?: { text: string };
|
||||||
conversation_id?: string | null;
|
conversation_id?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,16 +95,16 @@ export interface PipelineRun {
|
|||||||
stage: "ready" | "stt" | "intent" | "tts" | "done" | "error";
|
stage: "ready" | "stt" | "intent" | "tts" | "done" | "error";
|
||||||
run: PipelineRunStartEvent["data"];
|
run: PipelineRunStartEvent["data"];
|
||||||
error?: PipelineErrorEvent["data"];
|
error?: PipelineErrorEvent["data"];
|
||||||
stt?: PipelineSTTStartEvent["data"] & Partial<PipelineSTTFinishEvent["data"]>;
|
stt?: PipelineSTTStartEvent["data"] & Partial<PipelineSTTEndEvent["data"]>;
|
||||||
intent?: PipelineIntentStartEvent["data"] &
|
intent?: PipelineIntentStartEvent["data"] &
|
||||||
Partial<PipelineIntentFinishEvent["data"]>;
|
Partial<PipelineIntentEndEvent["data"]>;
|
||||||
tts?: PipelineTTSStartEvent["data"] & Partial<PipelineTTSFinishEvent["data"]>;
|
tts?: PipelineTTSStartEvent["data"] & Partial<PipelineTTSEndEvent["data"]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const runPipelineFromText = (
|
export const runPipelineFromText = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
callback: (event: PipelineRun) => void,
|
callback: (event: PipelineRun) => void,
|
||||||
options: PipelineRunOptions = {}
|
options: PipelineRunOptions
|
||||||
) => {
|
) => {
|
||||||
let run: PipelineRun | undefined;
|
let run: PipelineRun | undefined;
|
||||||
|
|
||||||
@ -121,17 +136,17 @@ export const runPipelineFromText = (
|
|||||||
|
|
||||||
if (updateEvent.type === "stt-start") {
|
if (updateEvent.type === "stt-start") {
|
||||||
run = { ...run, stage: "stt", stt: updateEvent.data };
|
run = { ...run, stage: "stt", stt: updateEvent.data };
|
||||||
} else if (updateEvent.type === "stt-finish") {
|
} else if (updateEvent.type === "stt-end") {
|
||||||
run = { ...run, stt: { ...run.stt!, ...updateEvent.data } };
|
run = { ...run, stt: { ...run.stt!, ...updateEvent.data } };
|
||||||
} else if (updateEvent.type === "intent-start") {
|
} else if (updateEvent.type === "intent-start") {
|
||||||
run = { ...run, stage: "intent", intent: updateEvent.data };
|
run = { ...run, stage: "intent", intent: updateEvent.data };
|
||||||
} else if (updateEvent.type === "intent-finish") {
|
} else if (updateEvent.type === "intent-end") {
|
||||||
run = { ...run, intent: { ...run.intent!, ...updateEvent.data } };
|
run = { ...run, intent: { ...run.intent!, ...updateEvent.data } };
|
||||||
} else if (updateEvent.type === "tts-start") {
|
} else if (updateEvent.type === "tts-start") {
|
||||||
run = { ...run, stage: "tts", tts: updateEvent.data };
|
run = { ...run, stage: "tts", tts: updateEvent.data };
|
||||||
} else if (updateEvent.type === "tts-finish") {
|
} else if (updateEvent.type === "tts-end") {
|
||||||
run = { ...run, tts: { ...run.tts!, ...updateEvent.data } };
|
run = { ...run, tts: { ...run.tts!, ...updateEvent.data } };
|
||||||
} else if (updateEvent.type === "run-finish") {
|
} else if (updateEvent.type === "run-end") {
|
||||||
run = { ...run, stage: "done" };
|
run = { ...run, stage: "done" };
|
||||||
unsubProm.then((unsub) => unsub());
|
unsubProm.then((unsub) => unsub());
|
||||||
} else if (updateEvent.type === "error") {
|
} else if (updateEvent.type === "error") {
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
import "../../../../../../layouts/hass-subpage";
|
import "../../../../../../layouts/hass-subpage";
|
||||||
import { SubscribeMixin } from "../../../../../../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../../../../../../mixins/subscribe-mixin";
|
||||||
import { haStyle } from "../../../../../../resources/styles";
|
import { haStyle } from "../../../../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../../../../types";
|
import type { HomeAssistant } from "../../../../../../types";
|
||||||
import { formatNumber } from "../../../../../../common/number/format_number";
|
import { formatNumber } from "../../../../../../common/number/format_number";
|
||||||
|
|
||||||
const RUN_DATA = {
|
const RUN_DATA = {
|
||||||
@ -25,11 +25,33 @@ const ERROR_DATA = {
|
|||||||
message: "Message",
|
message: "Message",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const STT_DATA = {
|
||||||
|
engine: "Engine",
|
||||||
|
};
|
||||||
|
|
||||||
const INTENT_DATA = {
|
const INTENT_DATA = {
|
||||||
engine: "Engine",
|
engine: "Engine",
|
||||||
intent_input: "Input",
|
intent_input: "Input",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TTS_DATA = {
|
||||||
|
engine: "Engine",
|
||||||
|
tts_input: "Input",
|
||||||
|
};
|
||||||
|
|
||||||
|
const STAGES: Record<PipelineRun["stage"], number> = {
|
||||||
|
ready: 0,
|
||||||
|
stt: 1,
|
||||||
|
intent: 2,
|
||||||
|
tts: 3,
|
||||||
|
done: 4,
|
||||||
|
error: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasStage = (run: PipelineRun, stage: PipelineRun["stage"]) =>
|
||||||
|
STAGES[run.init_options.start_stage] <= STAGES[stage] &&
|
||||||
|
STAGES[stage] <= STAGES[run.init_options.end_stage];
|
||||||
|
|
||||||
const renderProgress = (
|
const renderProgress = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
pipelineRun: PipelineRun,
|
pipelineRun: PipelineRun,
|
||||||
@ -39,7 +61,7 @@ const renderProgress = (
|
|||||||
(ev) => ev.type === `${stage}-start`
|
(ev) => ev.type === `${stage}-start`
|
||||||
);
|
);
|
||||||
const finishEvent = pipelineRun.events.find(
|
const finishEvent = pipelineRun.events.find(
|
||||||
(ev) => ev.type === `${stage}-finish`
|
(ev) => ev.type === `${stage}-end`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!startEvent) {
|
if (!startEvent) {
|
||||||
@ -142,25 +164,91 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) {
|
|||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
<ha-card>
|
|
||||||
<div class="card-content">
|
${hasStage(this._pipelineRun, "stt")
|
||||||
<div class="row heading">
|
? html`
|
||||||
<span>Natural Language Processing</span>
|
<ha-card>
|
||||||
${renderProgress(this.hass, this._pipelineRun, "intent")}
|
<div class="card-content">
|
||||||
</div>
|
<div class="row heading">
|
||||||
${this._pipelineRun.intent
|
<span>Speech-to-Text</span>
|
||||||
? html`
|
${renderProgress(
|
||||||
<div class="card-content">
|
this.hass,
|
||||||
${renderData(this._pipelineRun.intent, INTENT_DATA)}
|
this._pipelineRun,
|
||||||
${dataMinusKeysRender(
|
"stt"
|
||||||
this._pipelineRun.intent,
|
|
||||||
INTENT_DATA
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
`
|
${this._pipelineRun.stt
|
||||||
: ""}
|
? html`
|
||||||
</div>
|
<div class="card-content">
|
||||||
</ha-card>
|
${renderData(this._pipelineRun.stt, STT_DATA)}
|
||||||
|
${dataMinusKeysRender(
|
||||||
|
this._pipelineRun.stt,
|
||||||
|
STT_DATA
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${hasStage(this._pipelineRun, "intent")
|
||||||
|
? html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="row heading">
|
||||||
|
<span>Natural Language Processing</span>
|
||||||
|
${renderProgress(
|
||||||
|
this.hass,
|
||||||
|
this._pipelineRun,
|
||||||
|
"intent"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
${this._pipelineRun.intent
|
||||||
|
? html`
|
||||||
|
<div class="card-content">
|
||||||
|
${renderData(
|
||||||
|
this._pipelineRun.intent,
|
||||||
|
INTENT_DATA
|
||||||
|
)}
|
||||||
|
${dataMinusKeysRender(
|
||||||
|
this._pipelineRun.intent,
|
||||||
|
INTENT_DATA
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${hasStage(this._pipelineRun, "tts")
|
||||||
|
? html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="row heading">
|
||||||
|
<span>Text-to-Speech</span>
|
||||||
|
${renderProgress(
|
||||||
|
this.hass,
|
||||||
|
this._pipelineRun,
|
||||||
|
"tts"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
${this._pipelineRun.tts
|
||||||
|
? html`
|
||||||
|
<div class="card-content">
|
||||||
|
${renderData(this._pipelineRun.tts, TTS_DATA)}
|
||||||
|
${dataMinusKeysRender(
|
||||||
|
this._pipelineRun.tts,
|
||||||
|
TTS_DATA
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<ha-expansion-panel>
|
<ha-expansion-panel>
|
||||||
<span slot="header">Raw</span>
|
<span slot="header">Raw</span>
|
||||||
@ -182,7 +270,9 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) {
|
|||||||
this._pipelineRun = run;
|
this._pipelineRun = run;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
intent_input: this._newRunInput.value,
|
start_stage: "intent",
|
||||||
|
end_stage: "intent",
|
||||||
|
input: { text: this._newRunInput.value },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user