问题描述
我正在开发一个应用程序,该应用程序应显示与PC麦克风中听到的内容一致的字幕文本。
部分起作用,因为仅当在麦克风中讲话的人暂停时才返回文本。
如何在一定的时间间隔返回文本?
这是一个C#程序,但我认为问题在于传递给语音转文本API的选项。 RunAsync
是启动该过程的方法:
private const int SampleRate = 16000;
private const int ChannelCount = 1;
private const int BytesPerSample = 2;
private const int BytesPerSecond = SampleRate * ChannelCount * BytesPerSample;
/// <summary>
/// Runs the main loop until "exit" or "quit" is heard.
/// </summary>
private async Task RunAsync()
{
_streaming = true;
using (var microphone = StartListening())
{
while (_streaming)
{
await MaybeStartStreamAsync();
// ProcessResponses will return false if it hears "exit" or "quit".
if (!ProcessResponses())
{
return;
}
await TransferMicrophoneChunkAsync();
}
}
}
/// <summary>
/// Starts a new RPC streaming call if necessary. This will be if either it's the first call
/// (so we don't have a current request) or if the current request will time out soon.
/// In the latter case,after starting the new request,we copy any chunks we'd already sent
/// in the prevIoUs request which hadn't been included in a "final result".
/// </summary>
private async Task MaybeStartStreamAsync()
{
var Now = DateTime.UtcNow;
if (_rpcStream != null && Now >= _rpcStreamDeadline)
{
Console.WriteLine($"Closing stream before it times out");
await _rpcStream.WriteCompleteAsync();
_rpcStream.GrpcCall.dispose();
_rpcStream = null;
}
// If we have a valid stream at this point,we're fine.
if (_rpcStream != null)
{
return;
}
// We need to create a new stream,either because we're just starting or because we've just closed the prevIoUs one.
_rpcStream = _client.StreamingRecognize();
_rpcStreamDeadline = Now + s_streamTimeLimit;
_processingBufferStart = TimeSpan.Zero;
_serverResponseAvailableTask = _rpcStream.GetResponseStream().MoveNextAsync();
await _rpcStream.WriteAsync(new StreamingRecognizeRequest
{
StreamingConfig = new StreamingRecognitionConfig
{
Config = new RecognitionConfig
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,SampleRateHertz = SampleRate,LanguageCode = "en-US",MaxAlternatives = 1
},InterimResults = true,}
});
Console.WriteLine($"Writing {_processingBuffer.Count} chunks into the new stream.");
foreach (var chunk in _processingBuffer)
{
await WriteAudioChunk(chunk);
}
}
/// <summary>
/// Processes responses received so far from the server,/// returning whether "exit" or "quit" have been heard.
/// </summary>
private bool ProcessResponses()
{
while (_serverResponseAvailableTask.IsCompleted && _serverResponseAvailableTask.Result)
{
var response = _rpcStream.GetResponseStream().Current;
_serverResponseAvailableTask = _rpcStream.GetResponseStream().MoveNextAsync();
// Uncomment this to see the details of interim results.
// Console.WriteLine($"Response: {response}");
// See if one of the results is a "final result". If so,we trim our
// processing buffer.
var finalResult = response.Results.FirstOrDefault(r => r.IsFinal);
if (finalResult != null)
{
string transcript = finalResult.Alternatives[0].Transcript;
Console.WriteLine($"Transcript: {transcript}");
Transcript?.Invoke(this,new TranscriptEventArgs
{
Text = transcript
});
if (transcript.ToLowerInvariant().Contains("exit") ||
transcript.ToLowerInvariant().Contains("quit"))
{
return false;
}
TimeSpan resultEndTime = finalResult.ResultEndTime.ToTimeSpan();
// Rather than explicitly iterate over the list,we just always deal with the first
// element,either removing it or stopping.
int removed = 0;
while (_processingBuffer.First != null)
{
var sampleDuration = TimeSpan.FromSeconds(_processingBuffer.First.Value.Length / (double)BytesPerSecond);
var sampleEnd = _processingBufferStart + sampleDuration;
// If the first sample in the buffer ends after the result ended,stop.
// Note that part of the sample might have been included in the result,but the samples
// are short enough that this shouldn't cause problems.
if (sampleEnd > resultEndTime)
{
break;
}
_processingBufferStart = sampleEnd;
_processingBuffer.RemoveFirst();
removed++;
}
}
}
return true;
}
/// <summary>
/// Takes a single sample chunk from the microphone buffer,keeps a local copy
/// (in case we need to send it again in a new request) and sends it to the server.
/// </summary>
/// <returns></returns>
private async Task TransferMicrophoneChunkAsync()
{
// This will block - but only for ~100ms,unless something's really broken.
var chunk = _microphoneBuffer.Take();
_processingBuffer.AddLast(chunk);
await WriteAudioChunk(chunk);
}
/// <summary>
/// Writes a single chunk to the RPC stream.
/// </summary>
private Task WriteAudioChunk(ByteString chunk) =>
_rpcStream.WriteAsync(new StreamingRecognizeRequest { AudioContent = chunk });
/// <summary>
/// Starts listening to input device 0,and adds an event handler which simply adds
/// the sample to the microphone buffer. The returned <see cref="WaveInEvent"/> must
/// be disposed after we've finished with it.
/// </summary>
private WaveInEvent StartListening()
{
var waveIn = new WaveInEvent
{
DeviceNumber = 0,WaveFormat = new WaveFormat(SampleRate,ChannelCount)
};
waveIn.DataAvailable += (sender,args) =>
_microphoneBuffer.Add(ByteString.copyFrom(args.Buffer,args.BytesRecorded));
waveIn.StartRecording();
return waveIn;
}
我该怎么办?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)