adding audio gating (#705)
Co-authored-by: Marko Hietala <markhiet@microsoft.com>
This commit is contained in:
Родитель
4891677e7c
Коммит
8ac59e1b2d
|
@ -139,13 +139,14 @@ export class TranscriberRecognizer extends Recognizer {
|
|||
await reco.sendMeetingSpeechEventAsync(meetingInfo, command);
|
||||
}
|
||||
|
||||
public async checkAudioConfiguration(): Promise<void> {
|
||||
public async enforceAudioGating(): Promise<void> {
|
||||
const audioConfigImpl = this.audioConfig as AudioConfigImpl;
|
||||
const format: AudioStreamFormatImpl = await audioConfigImpl.format;
|
||||
const channels = format.channels;
|
||||
if (channels === 1) {
|
||||
// We use this GUID property to indicate that single channel audio is in use for MeetingTranscriber.
|
||||
this.properties.setProperty("f0f5debc-f8c9-4892-ac4b-90a7ab359fd2", "true");
|
||||
if (this.properties.getProperty("f0f5debc-f8c9-4892-ac4b-90a7ab359fd2", "false").toLowerCase() !== "true") {
|
||||
throw new Error("Single channel audio configuration for MeetingTranscriber is currently under private preview, please contact diarizationrequest@microsoft.com for more details");
|
||||
}
|
||||
} else if (channels !== 8) {
|
||||
throw new Error(`Unsupported audio configuration: Detected ${channels}-channel audio`);
|
||||
}
|
||||
|
|
|
@ -820,7 +820,7 @@ export class ConversationImpl extends Conversation implements IDisposable {
|
|||
if (!!this.privTranscriberRecognizer) {
|
||||
await this.privTranscriberRecognizer.close();
|
||||
}
|
||||
await recognizer.checkAudioConfiguration();
|
||||
await recognizer.enforceAudioGating();
|
||||
this.privTranscriberRecognizer = recognizer;
|
||||
this.privTranscriberRecognizer.conversation = this;
|
||||
}
|
||||
|
|
|
@ -773,7 +773,7 @@ export class MeetingImpl extends Meeting implements IDisposable {
|
|||
if (!!this.privTranscriberRecognizer) {
|
||||
await this.privTranscriberRecognizer.close();
|
||||
}
|
||||
await recognizer.checkAudioConfiguration();
|
||||
await recognizer.enforceAudioGating();
|
||||
this.privTranscriberRecognizer = recognizer;
|
||||
this.privTranscriberRecognizer.meeting = this;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,18 @@ const BuildMeetingTranscriber: () => sdk.MeetingTranscriber = (): sdk.MeetingTra
|
|||
return t;
|
||||
};
|
||||
|
||||
const BuildMonoWaveTranscriber: () => sdk.MeetingTranscriber = (): sdk.MeetingTranscriber => {
|
||||
|
||||
const config: sdk.AudioConfig = WaveFileAudioInput.getAudioConfigFromFile(Settings.DependentVerificationWaveFile);
|
||||
objsToClose.push(config);
|
||||
|
||||
const m: sdk.MeetingTranscriber = new sdk.MeetingTranscriber(config);
|
||||
expect(m).not.toBeUndefined();
|
||||
objsToClose.push(m);
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
const GetParticipantKatie: () => sdk.IParticipant = (): sdk.IParticipant => {
|
||||
const voiceSignatureKatie: string = `{
|
||||
Version: 0,
|
||||
|
@ -114,6 +126,7 @@ test("CreateMeetingTranscriber", () => {
|
|||
// eslint-disable-next-line no-console
|
||||
console.info("Name: CreateMeetingTranscriber");
|
||||
const t: sdk.MeetingTranscriber = BuildMeetingTranscriber();
|
||||
|
||||
expect(t.properties).not.toBeUndefined();
|
||||
});
|
||||
|
||||
|
@ -221,96 +234,6 @@ test("Create Meeting and add participants", (done: jest.DoneCallback) => {
|
|||
});
|
||||
}, 50000);
|
||||
|
||||
test("Create Meeting and add participants using single channel file", (done: jest.DoneCallback) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info("Name: Create Meeting and add participants using single channel file");
|
||||
const s: sdk.SpeechTranslationConfig = BuildSpeechConfig();
|
||||
objsToClose.push(s);
|
||||
|
||||
const m: sdk.Meeting = CreateMeeting(s);
|
||||
objsToClose.push(m);
|
||||
const config: sdk.AudioConfig = WaveFileAudioInput.getAudioConfigFromFile(Settings.WaveFileSingleChannel);
|
||||
objsToClose.push(config);
|
||||
|
||||
const t: sdk.MeetingTranscriber = new sdk.MeetingTranscriber(config);
|
||||
expect(t).not.toBeUndefined();
|
||||
objsToClose.push(t);
|
||||
let userFound: boolean = false;
|
||||
|
||||
t.sessionStopped = (o: sdk.MeetingTranscriber, e: sdk.SessionEventArgs) => {
|
||||
try {
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
t.canceled = (o: sdk.MeetingTranscriber, e: sdk.MeetingTranscriptionCanceledEventArgs) => {
|
||||
try {
|
||||
expect(e.errorDetails).toBeUndefined();
|
||||
expect(e.reason).toEqual(sdk.CancellationReason.EndOfStream);
|
||||
expect(userFound).toEqual(true);
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
|
||||
t.transcribed = (o: sdk.MeetingTranscriber, e: sdk.MeetingTranscriptionEventArgs) => {
|
||||
try {
|
||||
expect(e).not.toBeUndefined();
|
||||
expect(e.result).not.toBeUndefined();
|
||||
expect(sdk.ResultReason[e.result.reason]).toEqual(sdk.ResultReason[sdk.ResultReason.RecognizedSpeech]);
|
||||
expect(e.result.text).not.toBeUndefined();
|
||||
expect(e.result.speakerId).not.toBeUndefined();
|
||||
// eslint-disable-next-line no-console
|
||||
console.info("[Transcribed] SpeakerId: " + e.result.speakerId + " Text:" + e.result.text);
|
||||
if (e.result.speakerId.startsWith("katie") || e.result.speakerId.startsWith("steve")) {
|
||||
userFound = true;
|
||||
}
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
|
||||
t.joinMeetingAsync(m,
|
||||
() => {
|
||||
try {
|
||||
expect(t.properties).not.toBeUndefined();
|
||||
m.addParticipantAsync(GetParticipantKatie(),
|
||||
() => {
|
||||
try {
|
||||
expect(m.participants).not.toBeUndefined();
|
||||
expect(m.participants.length).toEqual(1);
|
||||
// Adds steve as a participant to the conversation.
|
||||
m.addParticipantAsync(GetParticipantSteve(),
|
||||
() => {
|
||||
try {
|
||||
expect(m.participants).not.toBeUndefined();
|
||||
expect(m.participants.length).toEqual(2);
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
|
||||
/* eslint-disable:no-empty */
|
||||
t.startTranscribingAsync(
|
||||
/* eslint-disable:no-empty */
|
||||
() => {},
|
||||
(err: string) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
},
|
||||
(error: string) => {
|
||||
done(error);
|
||||
});
|
||||
}, 50000);
|
||||
|
||||
test("Leave Meeting", (done: jest.DoneCallback) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info("Name: Leave Meeting");
|
||||
|
@ -348,7 +271,7 @@ test("Leave Meeting", (done: jest.DoneCallback) => {
|
|||
try {
|
||||
expect(m.participants).not.toBeUndefined();
|
||||
expect(m.participants.length).toEqual(2);
|
||||
// Start transcribing, then leave conversation immediately. Expected to detach all text result listeners.
|
||||
// Start transcribing, then leave meeting immediately. Expected to detach all text result listeners.
|
||||
/* eslint-disable:no-empty */
|
||||
t.startTranscribingAsync(
|
||||
(): void => {
|
||||
|
@ -388,28 +311,104 @@ test("Leave Meeting", (done: jest.DoneCallback) => {
|
|||
});
|
||||
});
|
||||
|
||||
test("Create Meeting with one channel does not throw", (done: jest.DoneCallback): void => {
|
||||
test("Create Meeting with one channel throws", (done: jest.DoneCallback): void => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info("Name: Create Meeting with one channel does not throw");
|
||||
console.info("Name: Create Meeting with one channel audio (aligned)");
|
||||
const s: sdk.SpeechTranslationConfig = BuildSpeechConfig();
|
||||
objsToClose.push(s);
|
||||
|
||||
const m: sdk.Meeting = CreateMeeting(s);
|
||||
objsToClose.push(m);
|
||||
|
||||
const config: sdk.AudioConfig = WaveFileAudioInput.getAudioConfigFromFile(Settings.DependentVerificationWaveFile);
|
||||
objsToClose.push(config);
|
||||
|
||||
const t: sdk.MeetingTranscriber = new sdk.MeetingTranscriber(config);
|
||||
expect(t).not.toBeUndefined();
|
||||
objsToClose.push(t);
|
||||
const t: sdk.MeetingTranscriber = BuildMonoWaveTranscriber();
|
||||
|
||||
t.joinMeetingAsync(m,
|
||||
(): void => {
|
||||
done();
|
||||
done.fail("No successful callback expected for single channel CTS");
|
||||
},
|
||||
(error: string): void => {
|
||||
done.fail("No error callback expected for single channel CTS");
|
||||
expect(error).toEqual("Error: Single channel audio configuration for MeetingTranscriber is currently under private preview, please contact diarizationrequest@microsoft.com for more details");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test.skip("Create Conversation with one channel audio (aligned)", (done: jest.DoneCallback): void => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info("Name: Create Conversation with one channel audio (aligned)");
|
||||
const s: sdk.SpeechTranslationConfig = BuildSpeechConfig();
|
||||
objsToClose.push(s);
|
||||
|
||||
const m: sdk.Meeting = CreateMeeting(s);
|
||||
objsToClose.push(m);
|
||||
let sessionId: string = "";
|
||||
let canceled: boolean = false;
|
||||
|
||||
const t: sdk.MeetingTranscriber = BuildMonoWaveTranscriber();
|
||||
t.canceled = (o: sdk.MeetingTranscriber, e: sdk.MeetingTranscriptionCanceledEventArgs) => {
|
||||
try {
|
||||
expect(e.errorDetails).toBeUndefined();
|
||||
expect(e.reason).toEqual(sdk.CancellationReason.EndOfStream);
|
||||
canceled = true;
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
t.sessionStopped = (o: sdk.MeetingTranscriber, e: sdk.SessionEventArgs) => {
|
||||
try {
|
||||
expect(canceled).toEqual(true);
|
||||
expect(e.sessionId).not.toBeUndefined();
|
||||
expect(e.sessionId).toEqual(sessionId);
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
t.sessionStarted = (o: sdk.MeetingTranscriber, e: sdk.SessionEventArgs) => {
|
||||
try {
|
||||
expect(e.sessionId).not.toBeUndefined();
|
||||
sessionId = e.sessionId;
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
|
||||
t.transcribed = (o: sdk.MeetingTranscriber, e: sdk.MeetingTranscriptionEventArgs) => {
|
||||
try {
|
||||
expect(e.result).not.toBeUndefined();
|
||||
expect(e.result.text).not.toBeUndefined();
|
||||
expect(e.result.text).toEqual("");
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
};
|
||||
|
||||
t.transcribing = (o: sdk.MeetingTranscriber, e: sdk.MeetingTranscriptionEventArgs) => {
|
||||
done(e.result.errorDetails);
|
||||
};
|
||||
|
||||
t.joinMeetingAsync(m,
|
||||
() => {
|
||||
try {
|
||||
expect(t.properties).not.toBeUndefined();
|
||||
m.addParticipantAsync(GetParticipantKatie(),
|
||||
() => {
|
||||
/* eslint-disable:no-empty */
|
||||
t.startTranscribingAsync(
|
||||
/* eslint-disable:no-empty */
|
||||
() => { },
|
||||
(err: string) => {
|
||||
done(err);
|
||||
});
|
||||
},
|
||||
(error: string) => {
|
||||
done(error);
|
||||
});
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
},
|
||||
(error: string) => {
|
||||
done(error);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче