텍스트를 입력하면 음성으로 변환해
응답속도를 높이기 위한
_ = Task.Run(() => GetChatCompletion(command.Text));
var recVoice = _openAIService.ConvertTextToVoiceAsync(command.Text, command.Voice).Result;
_blazorCallback?.Invoke("AddMessage", new object[] { command.From, command.Text });
_blazorCallback?.Invoke("PlayAudioBytes", new object[] { recVoice, 0.5f, playType });
- Text가 입력되면 TTS 음성파일을 준비하는 동안, LLM요청을 분리된 스레드에서 요청합니다.
private float[] ConvertMp3ToFloatArray(byte[] mp3Data)
{
using var mp3Stream = new MemoryStream(mp3Data);
using var mp3Reader = new Mp3FileReader(mp3Stream);
// PCM 데이터를 float 배열로 변환
var sampleProvider = mp3Reader.ToSampleProvider();
var totalSamples = (int)(mp3Reader.TotalTime.TotalSeconds * mp3Reader.WaveFormat.SampleRate * mp3Reader.WaveFormat.Channels);
var floatBuffer = new float[totalSamples];
int samplesRead = sampleProvider.Read(floatBuffer, 0, floatBuffer.Length);
return floatBuffer.Take(samplesRead).ToArray();
}
async function playAudioBytes(audioBytes, playbackRate, type, dotNetRef) {
try {
if (!audioContext || audioContext.state === 'closed') {
audioContext = new AudioContext();
}
// Float32Array로 변환된 PCM 데이터 사용
const float32Array = new Float32Array(audioBytes);
// AudioBuffer 생성
const audioBuffer = audioContext.createBuffer(1, float32Array.length, audioContext.sampleRate);
audioBuffer.copyToChannel(float32Array, 0);
// 재생
const bufferSource = audioContext.createBufferSource();
bufferSource.buffer = audioBuffer;
bufferSource.playbackRate.value = playbackRate; // 재생 속도 설정
bufferSource.connect(audioContext.destination);
// 재생 완료 이벤트 핸들러 추가
bufferSource.onended = () => {
// 타입에 따라 추가 작업 수행
console.log(`오디오 재생 완료 재생 타입: ${type}`);
if (type === 1) {
console.log("Type 1: 휴먼 재생완료~ LLM응답요청");
if (dotNetRef && typeof dotNetRef.invokeMethodAsync === "function") {
dotNetRef.invokeMethodAsync("OnAudioPlaybackCompleted", 1)
.catch(err => console.error("Blazor 메서드 호출 OnAudioPlaybackCompleted 중 오류 발생:", err));
}
} else if (type === 2) {
console.log("Type 2: AI재생완료");
} else if (type === 3) {
console.log("Type 3: 사용자 정의 작업");
}
};
bufferSource.start();
} catch (err) {
console.error("오디오 재생 중 오류 발생:", err);
}
}
<PageTitle>WebRTC</PageTitle>
<h1>WebRTC</h1>
<!-- 채팅창 -->
<MudItem xs="12">
<MudPaper Class="pa-3">
<MudButton OnClick="StartWebRTC" Class="mt-4">
Start WebRTC
</MudButton>
</MudPaper>
<MudPaper Class="pa-3">
<MudText Typo="Typo.subtitle1">채팅</MudText>
<MudStack>
<!-- 채팅 리스트 -->
<MudList T="string">
@foreach (var chat in ChatMessages)
{
<MudListItem Text="@chat" Icon="@Icons.Material.Filled.Chat" />
}
</MudList>
<!-- 채팅 입력 -->
<MudTextField @bind-Value="ChatInput" Placeholder="메시지를 입력하세요..." />
<MudButton OnClick="SendChatMessage" Class="mt-2">전송</MudButton>
</MudStack>
</MudPaper>
</MudItem>
@code {
[JSInvokable]
public async Task OnAudioPlaybackCompleted(int option)
{
MyVoiceActor.Tell(new TTSCommand()
{
From = "AI",
Text = "LLM자동재생",
Voice = "alloy"
});
}
private void PlayAudioBytes(float[] voice, float speed, int playtype)
{
InvokeAsync(() =>
{
var dotNetRef = DotNetObjectReference.Create(this);
JSRuntime.InvokeVoidAsync("playAudioBytes", voice, speed, playtype, dotNetRef);
});
}
}
