mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-25 09:30:27 +00:00
Merge branch 'develop' into staging-new
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
commit
1484b9893a
@ -88,7 +88,7 @@
|
|||||||
<div class="flex-center clear-mins w-full h-9">
|
<div class="flex-center clear-mins w-full h-9">
|
||||||
{#if issue?.$lookup?.status}
|
{#if issue?.$lookup?.status}
|
||||||
<div class="icon mr-4 h-8">
|
<div class="icon mr-4 h-8">
|
||||||
<IssueStatusIcon value={issue.$lookup.status} space={issue.space} size="small" />
|
<IssueStatusIcon value={issue.$lookup.status} taskType={issue.kind} space={issue.space} size="small" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="overflow-label flex-no-shrink mr-3">{issue.identifier}</span>
|
<span class="overflow-label flex-no-shrink mr-3">{issue.identifier}</span>
|
||||||
|
@ -20,14 +20,14 @@
|
|||||||
|
|
||||||
export let tx: TxUpdateDoc<Issue>
|
export let tx: TxUpdateDoc<Issue>
|
||||||
$: value = tx.operations.status
|
$: value = tx.operations.status
|
||||||
|
$: taskType = tx.operations.kind
|
||||||
|
|
||||||
$: status = value && $statusStore.byId.get(value)
|
$: status = value && $statusStore.byId.get(value)
|
||||||
|
|
||||||
$: space = tx.objectSpace as Ref<Project>
|
$: space = tx.objectSpace as Ref<Project>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
{#if status}
|
{#if status}
|
||||||
<IssueStatusIcon value={status} {space} size="small" on:accent-color />
|
<IssueStatusIcon value={status} {taskType} {space} size="small" on:accent-color />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<!-- <Icon icon={tracker.icon.TrackerApplication} size={'medium'} /> -->
|
<!-- <Icon icon={tracker.icon.TrackerApplication} size={'medium'} /> -->
|
||||||
<FixedColumn key="object-popup-issue-status">
|
<FixedColumn key="object-popup-issue-status">
|
||||||
{#if st}
|
{#if st}
|
||||||
<IssueStatusIcon value={st} size={'small'} space={value.space} />
|
<IssueStatusIcon value={st} taskType={value.kind} size={'small'} space={value.space} />
|
||||||
{/if}
|
{/if}
|
||||||
</FixedColumn>
|
</FixedColumn>
|
||||||
<span class="ml-2 max-w-120 overflow-label">
|
<span class="ml-2 max-w-120 overflow-label">
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
<div class="flex-row-center flex-wrap gap-2 reverse">
|
<div class="flex-row-center flex-wrap gap-2 reverse">
|
||||||
{#if status === undefined && issue}
|
{#if status === undefined && issue}
|
||||||
<IssueStatusIcon value={status} space={issue.space} size="small" />
|
<IssueStatusIcon value={status} taskType={issue.kind} space={issue.space} size="small" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if issue}
|
{#if issue}
|
||||||
<IssuePresenter value={issue} />
|
<IssuePresenter value={issue} />
|
||||||
|
@ -86,6 +86,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</Row>
|
</Row>
|
||||||
{#each displaySt as st}
|
{#each displaySt as st}
|
||||||
<StatusPresenter value={st.status} space={issue.space} />
|
<StatusPresenter value={st.status} taskType={issue.kind} space={issue.space} />
|
||||||
<Duration value={st.duration} />
|
<Duration value={st.duration} />
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -31,5 +31,5 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value}
|
{#if value}
|
||||||
<IssueStatusIcon value={issueStatus} {size} space={value.space} />
|
<IssueStatusIcon value={issueStatus} taskType={value.kind} {size} space={value.space} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -143,6 +143,7 @@
|
|||||||
<div class="flex-center flex-no-shrink square-4">
|
<div class="flex-center flex-no-shrink square-4">
|
||||||
{#if selectedStatus}<IssueStatusIcon
|
{#if selectedStatus}<IssueStatusIcon
|
||||||
value={selectedStatus}
|
value={selectedStatus}
|
||||||
|
taskType={value.kind}
|
||||||
size={kind === 'list' ? 'small' : 'medium'}
|
size={kind === 'list' ? 'small' : 'medium'}
|
||||||
space={value.space}
|
space={value.space}
|
||||||
/>{/if}
|
/>{/if}
|
||||||
@ -170,7 +171,7 @@
|
|||||||
>
|
>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
{#if selectedStatus}
|
{#if selectedStatus}
|
||||||
<IssueStatusIcon value={selectedStatus} size={iconSize} space={value.space} />
|
<IssueStatusIcon value={selectedStatus} taskType={value.kind} size={iconSize} space={value.space} />
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
|
@ -139,7 +139,7 @@
|
|||||||
>
|
>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
{#if selectedStatus}
|
{#if selectedStatus}
|
||||||
<IssueStatusIcon value={selectedStatus} size={iconSize} space={undefined} />
|
<IssueStatusIcon value={selectedStatus} {taskType} size={iconSize} space={undefined} />
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
|
@ -161,7 +161,7 @@
|
|||||||
>
|
>
|
||||||
{#if parentStatus}
|
{#if parentStatus}
|
||||||
<div class="pr-2">
|
<div class="pr-2">
|
||||||
<IssueStatusIcon space={parentIssue.space} value={parentStatus} size="small" />
|
<IssueStatusIcon space={parentIssue.space} taskType={parentIssue.kind} value={parentStatus} size="small" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="overflow-label flex-no-shrink mr-2">{parentIssue.identifier}</span>
|
<span class="overflow-label flex-no-shrink mr-2">{parentIssue.identifier}</span>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<div class="flex-row-center">
|
<div class="flex-row-center">
|
||||||
{#if status}
|
{#if status}
|
||||||
<div class="icon mr-2">
|
<div class="icon mr-2">
|
||||||
<IssueStatusIcon value={status} {size} space={issue.space} />
|
<IssueStatusIcon value={status} taskType={issue.kind} {size} space={issue.space} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="label" class:text-base={huge}>
|
<span class="label" class:text-base={huge}>
|
||||||
|
@ -28,6 +28,14 @@ interface Config {
|
|||||||
VadSilenceDurationMs: number
|
VadSilenceDurationMs: number
|
||||||
VadPrefixPaddingMs: number
|
VadPrefixPaddingMs: number
|
||||||
VadThreshold: number
|
VadThreshold: number
|
||||||
|
|
||||||
|
DgEndpointing: number
|
||||||
|
DgUtteranceEndMs: number
|
||||||
|
DgInterimResults: boolean
|
||||||
|
DgVadEvents: boolean
|
||||||
|
DgPunctuate: boolean
|
||||||
|
DgSmartFormat: boolean
|
||||||
|
DgNoDelay: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const config: Config = (() => {
|
const config: Config = (() => {
|
||||||
@ -43,7 +51,15 @@ const config: Config = (() => {
|
|||||||
SttProvider: (process.env.STT_PROVIDER as SttProvider) ?? 'deepgram',
|
SttProvider: (process.env.STT_PROVIDER as SttProvider) ?? 'deepgram',
|
||||||
VadSilenceDurationMs: parseInt(process.env.SILENCE_DURATION_MS ?? '1000'),
|
VadSilenceDurationMs: parseInt(process.env.SILENCE_DURATION_MS ?? '1000'),
|
||||||
VadPrefixPaddingMs: parseInt(process.env.PREFIX_PADDING_MS ?? '1000'),
|
VadPrefixPaddingMs: parseInt(process.env.PREFIX_PADDING_MS ?? '1000'),
|
||||||
VadThreshold: parseFloat(process.env.VAD_THRESHOLD ?? '0.5')
|
VadThreshold: parseFloat(process.env.VAD_THRESHOLD ?? '0.5'),
|
||||||
|
|
||||||
|
DgEndpointing: parseInt(process.env.DG_ENDPOINTING ?? '100'),
|
||||||
|
DgInterimResults: process.env.DG_INTERIM_RESULTS === 'true',
|
||||||
|
DgVadEvents: process.env.DG_VAD_EVENTS === 'true',
|
||||||
|
DgPunctuate: process.env.DG_PUNCTUATE === 'true',
|
||||||
|
DgSmartFormat: process.env.DG_SMART_FORMAT === 'true',
|
||||||
|
DgUtteranceEndMs: parseInt(process.env.DG_UTTERANCE_END_MS ?? '0'),
|
||||||
|
DgNoDelay: process.env.DG_NO_DELAY === 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
const missingEnv = (Object.keys(params) as Array<keyof Config>).filter((key) => params[key] === undefined)
|
const missingEnv = (Object.keys(params) as Array<keyof Config>).filter((key) => params[key] === undefined)
|
||||||
|
@ -29,19 +29,6 @@ import config from '../config.js'
|
|||||||
|
|
||||||
const KEEP_ALIVE_INTERVAL = 10 * 1000
|
const KEEP_ALIVE_INTERVAL = 10 * 1000
|
||||||
|
|
||||||
const dgSchema: LiveSchema = {
|
|
||||||
model: config.DeepgramModel,
|
|
||||||
encoding: 'linear16',
|
|
||||||
smart_format: true,
|
|
||||||
endpointing: 500,
|
|
||||||
interim_results: true,
|
|
||||||
vad_events: true,
|
|
||||||
utterance_end_ms: 1000,
|
|
||||||
|
|
||||||
punctuate: true,
|
|
||||||
language: 'en'
|
|
||||||
}
|
|
||||||
|
|
||||||
export class STT implements Stt {
|
export class STT implements Stt {
|
||||||
private readonly deepgram: DeepgramClient
|
private readonly deepgram: DeepgramClient
|
||||||
|
|
||||||
@ -134,6 +121,47 @@ export class STT implements Stt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOptions (stream: AudioStream): LiveSchema {
|
||||||
|
const options: Partial<LiveSchema> = {}
|
||||||
|
|
||||||
|
if (config.DgEndpointing !== 0) {
|
||||||
|
options.endpointing = config.DgEndpointing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgInterimResults) {
|
||||||
|
options.interim_results = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgVadEvents) {
|
||||||
|
options.vad_events = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgUtteranceEndMs !== 0) {
|
||||||
|
options.utterance_end_ms = config.DgUtteranceEndMs
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgPunctuate) {
|
||||||
|
options.punctuate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgSmartFormat) {
|
||||||
|
options.smart_format = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.DgNoDelay) {
|
||||||
|
options.no_delay = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
encoding: 'linear16',
|
||||||
|
channels: stream.numChannels,
|
||||||
|
sample_rate: stream.sampleRate,
|
||||||
|
language: 'multi',
|
||||||
|
model: config.DeepgramModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
processTrack (sid: string): void {
|
processTrack (sid: string): void {
|
||||||
const track = this.trackBySid.get(sid)
|
const track = this.trackBySid.get(sid)
|
||||||
if (track === undefined) return
|
if (track === undefined) return
|
||||||
@ -141,14 +169,9 @@ export class STT implements Stt {
|
|||||||
|
|
||||||
const stream = new AudioStream(track)
|
const stream = new AudioStream(track)
|
||||||
// const language = this.language ?? 'en'
|
// const language = this.language ?? 'en'
|
||||||
const dgConnection = this.deepgram.listen.live({
|
const options = this.getOptions(stream)
|
||||||
...dgSchema,
|
const dgConnection = this.deepgram.listen.live(options)
|
||||||
channels: stream.numChannels,
|
console.log('Starting deepgram for track', this.room.name, sid, options)
|
||||||
sample_rate: stream.sampleRate,
|
|
||||||
language: 'multi',
|
|
||||||
model: config.DeepgramModel
|
|
||||||
})
|
|
||||||
console.log('Starting deepgram for track', this.room.name, sid)
|
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
dgConnection.keepAlive()
|
dgConnection.keepAlive()
|
||||||
@ -167,14 +190,13 @@ export class STT implements Stt {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.speech_final === true) {
|
if (data.speech_final === true || data.is_final === true) {
|
||||||
void this.sendToPlatform(transcript, sid)
|
|
||||||
} else if (data.is_final === true) {
|
|
||||||
void this.sendToPlatform(transcript, sid)
|
void this.sendToPlatform(transcript, sid)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
dgConnection.on(LiveTranscriptionEvents.Close, (d) => {
|
dgConnection.on(LiveTranscriptionEvents.Close, (data) => {
|
||||||
|
console.log('Deepgram closed', data)
|
||||||
this.stopDeepgram(sid)
|
this.stopDeepgram(sid)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user