Date: Fri, 13 May 2022 08:12:36 +0000
Subject: [PATCH 08/45] =?UTF-8?q?!2780=20feat(#I57AGS):=20improve=20speech?=
=?UTF-8?q?=20component=20*=20chore:=20bump=20version=206.0.8=20*=20feat:?=
=?UTF-8?q?=20=E8=B6=85=E6=97=B6=E5=9B=9E=E8=B0=83=E6=94=B9=E4=B8=BA?=
=?UTF-8?q?=E5=BC=82=E6=AD=A5=20*=20refactor:=20=E8=B0=83=E7=94=A8=20Baidu?=
=?UTF-8?q?=20Api=20=E6=94=B9=E4=B8=BA=E5=BC=82=E6=AD=A5=E8=B0=83=E7=94=A8?=
=?UTF-8?q?=20*=20refactor:=20=E7=A7=BB=E9=99=A4=E8=AE=B0=E5=BD=95?=
=?UTF-8?q?=E8=B0=83=E7=94=A8=E6=96=B9=E6=B3=95=E6=97=A5=E5=BF=97=20*=20ch?=
=?UTF-8?q?ore:=20bump=20verson=206.0.3=20*=20doc:=20=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=E5=8F=82=E6=95=B0=E5=90=8D=E7=A7=B0=20*=20Merge=20branch=20'ma?=
=?UTF-8?q?in'=20into=20feat-azure=20*=20doc:=20=E8=AF=AD=E9=9F=B3?=
=?UTF-8?q?=E5=AE=9E=E6=88=98=E5=A2=9E=E5=8A=A0=E6=97=B6=E9=95=BF=E6=98=BE?=
=?UTF-8?q?=E7=A4=BA=20*=20doc:=20=E8=AF=AD=E9=9F=B3=E8=AF=86=E5=88=AB?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=B6=E9=95=BF=E6=98=BE=E7=A4=BA=20*=20do?=
=?UTF-8?q?c:=20=E6=9B=B4=E6=96=B0=E5=8F=82=E6=95=B0=E6=B3=A8=E9=87=8A=20*?=
=?UTF-8?q?=20refactor:=20=E6=9B=B4=E6=94=B9=E6=96=B9=E6=B3=95=E5=90=8D?=
=?UTF-8?q?=E7=A7=B0=20*=20feat:=20=E4=BF=AE=E5=A4=8D=20Token=20=E6=8A=A5?=
=?UTF-8?q?=E9=94=99=E9=80=BB=E8=BE=91=20*=20feat:=20=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E5=88=A4=E6=96=AD=E9=98=B2=E6=AD=A2=E6=8A=A5=E9=94=99=20*=20fe?=
=?UTF-8?q?at:=20=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=20*=20feat:=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8=E5=85=B3=E9=97=AD=E5=8F=82?=
=?UTF-8?q?=E6=95=B0=20*=20feat:=20=E5=A2=9E=E5=8A=A0=E8=B6=85=E6=97=B6?=
=?UTF-8?q?=E5=88=A4=E5=AE=9A=E9=80=BB=E8=BE=91=20*=20refactor:=20?=
=?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=B3=A8=E5=85=A5=E6=8E=A7=E5=88=B6=E5=99=A8?=
=?UTF-8?q?=E6=9C=8D=E5=8A=A1=20*=20refactor:=20=E6=9B=B4=E6=96=B0=20Speec?=
=?UTF-8?q?hWave=20=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/BootstrapBlazor.Server/Program.cs | 1 -
.../Samples/Speechs/Recognizers.razor | 2 +-
.../Samples/Speechs/Recognizers.razor.cs | 10 +++--
.../Samples/Speechs/SpeechWaves.razor.cs | 4 +-
.../Samples/Speechs/Speechs.razor | 9 ++---
.../Samples/Speechs/Speechs.razor.cs | 23 ++++++-----
.../Samples/Speechs/Synthesizers.razor.cs | 9 +++--
.../Components/Speech/SpeechWave.razor.cs | 15 +++----
.../BootstrapBlazor.AzureSpeech.csproj | 2 +-
.../Extensions/RecognizerServiceExtensions.cs | 20 ++++++++--
.../SynthesizerServiceExtensions.cs | 8 ++--
.../Services/AzureRecognizerProvider.cs | 40 ++++++++++---------
.../Services/AzureSynthesizerProvider.cs | 19 ++++++---
.../wwwroot/js/speech.js | 16 +++++++-
.../BootstrapBlazor.BaiduSpeech.csproj | 2 +-
.../Services/BaiduRecognizerProvider.cs | 35 ++++++++--------
16 files changed, 127 insertions(+), 88 deletions(-)
diff --git a/src/BootstrapBlazor.Server/Program.cs b/src/BootstrapBlazor.Server/Program.cs
index 7b95b867e..03b739373 100644
--- a/src/BootstrapBlazor.Server/Program.cs
+++ b/src/BootstrapBlazor.Server/Program.cs
@@ -15,7 +15,6 @@ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
builder.Services.AddCors();
builder.Services.AddResponseCompression();
-builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor b/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor
index d94c05fb3..b38f76efa 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor
@@ -11,7 +11,7 @@
点击 开始识别 后,脚本运行可能会提示要求录音权限,授权后开始讲话,5秒后(可配置)右侧文本框显示语音识别结果,请勿讲完话后直接点击 结束识别
-
+
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor.cs b/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor.cs
index 7078f3ed1..7f1513afc 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor.cs
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/Recognizers.razor.cs
@@ -26,7 +26,7 @@ public partial class Recognizers
{
if (ButtonText == "开始识别")
{
- await RecognizerService.RecognizeOnceAsync(Recognize);
+ await RecognizerService.RecognizeOnceAsync(Recognize, 5000);
}
else
{
@@ -55,11 +55,13 @@ public partial class Recognizers
Start = false;
ButtonText = "开始识别";
}
-
- if (status != RecognizerStatus.Close)
+ else
{
- StateHasChanged();
+ Result = "";
+ Start = false;
+ ButtonText = "开始识别";
}
+ StateHasChanged();
return Task.CompletedTask;
}
}
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/SpeechWaves.razor.cs b/src/BootstrapBlazor.Shared/Samples/Speechs/SpeechWaves.razor.cs
index f4ea840c9..a99f62dd8 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/SpeechWaves.razor.cs
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/SpeechWaves.razor.cs
@@ -50,11 +50,11 @@ public partial class SpeechWaves
DefaultValue = " — "
},
new AttributeItem() {
- Name = nameof(SpeechWave.TotalTimeSecond),
+ Name = nameof(SpeechWave.TotalTime),
Description = Localizer["TotalTimeSecondAttr"],
Type = "int",
ValueList = " — ",
- DefaultValue = "60"
+ DefaultValue = "60000"
}
};
}
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor b/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor
index 4a22a3edc..cf4ad7952 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor
@@ -7,7 +7,7 @@
通过麦克风语音采集转换为文字(STT),或者通过文字通过语音朗读出来(TTS)
-
本组件依赖于 @NugetPackageName,使用本组件时需要引用其组件包
+
本套组件内置 Azure 与 Baidu 语音服务,本示例依赖于 @NugetPackageName,使用本组件时需要引用其组件包
Nuget 包安装
@@ -36,7 +36,7 @@
-
+
@@ -48,10 +48,7 @@
Program.cs
-// 增加 Azure 语音服务
-builder.Services.AddBootstrapBlazorAzureSpeech();
-
-// 增加 Baidu 语音服务
+// 增加 Baidu 语音服务
builder.Services.AddBootstrapBlazorBaiduSpeech();
2. 使用服务
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor.cs b/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor.cs
index 608efacd5..a25a798de 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor.cs
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/Speechs.razor.cs
@@ -34,6 +34,8 @@ public partial class Speechs
[NotNull]
private static string NugetPackageName => "BootstrapBlazor.BaiduSpeech";
+ private int TotalTime { get; set; } = 5000;
+
///
/// OnInitializedAsync 方法
///
@@ -45,7 +47,8 @@ public partial class Speechs
private async Task OnStart()
{
- await RecognizerService.RecognizeOnceAsync(Recognizer);
+ TotalTime = 5000;
+ await RecognizerService.RecognizeOnceAsync(Recognizer, TotalTime);
}
private Task Recognizer(RecognizerStatus status, string? result)
@@ -84,7 +87,7 @@ public partial class Speechs
Message = text,
Color = Color.Warning
});
- await InvokeAsync(StateHasChanged);
+ StateHasChanged();
}
if (status == SynthesizerStatus.Finished)
{
@@ -92,14 +95,15 @@ public partial class Speechs
}
});
}
- }).ConfigureAwait(false);
+ });
private async Task RecognizerConfirm()
{
Show = true;
- await InvokeAsync(StateHasChanged);
+ TotalTime = 3000;
+ StateHasChanged();
await Task.Delay(300);
- await RecognizerService.RecognizeOnceAsync(Confirm);
+ await RecognizerService.RecognizeOnceAsync(Confirm, TotalTime);
}
private async Task Confirm(RecognizerStatus status, string? result)
@@ -112,7 +116,7 @@ public partial class Speechs
else
{
Show = false;
- await InvokeAsync(StateHasChanged);
+ StateHasChanged();
}
result ??= "";
@@ -129,12 +133,12 @@ public partial class Speechs
Message = "指令发送中...",
Color = Color.Warning
});
- await InvokeAsync(StateHasChanged);
+ StateHasChanged();
//模拟后台执行任务
await Task.Delay(2000);
- await SynthesizerService.SynthesizerOnceAsync("已经为您打开", async status =>
+ await SynthesizerService.SynthesizerOnceAsync("已经为您打开", status =>
{
if (status == SynthesizerStatus.Synthesizer)
{
@@ -143,8 +147,9 @@ public partial class Speechs
Message = "已经为您打开",
Color = Color.Danger
});
- await InvokeAsync(StateHasChanged);
+ StateHasChanged();
}
+ return Task.CompletedTask;
});
}
}
diff --git a/src/BootstrapBlazor.Shared/Samples/Speechs/Synthesizers.razor.cs b/src/BootstrapBlazor.Shared/Samples/Speechs/Synthesizers.razor.cs
index b22d2bd44..8b12df801 100644
--- a/src/BootstrapBlazor.Shared/Samples/Speechs/Synthesizers.razor.cs
+++ b/src/BootstrapBlazor.Shared/Samples/Speechs/Synthesizers.razor.cs
@@ -26,15 +26,18 @@ public partial class Synthesizers
{
if (ButtonText == "开始合成")
{
- await SynthesizerService.SynthesizerOnceAsync(InputText, Recognize);
+ if (!string.IsNullOrEmpty(InputText))
+ {
+ await SynthesizerService.SynthesizerOnceAsync(InputText, Synthesizer);
+ }
}
else
{
- await SynthesizerService.CloseAsync(Recognize);
+ await SynthesizerService.CloseAsync(Synthesizer);
}
}
- private Task Recognize(SynthesizerStatus status)
+ private Task Synthesizer(SynthesizerStatus status)
{
if (status == SynthesizerStatus.Synthesizer)
{
diff --git a/src/BootstrapBlazor/Components/Speech/SpeechWave.razor.cs b/src/BootstrapBlazor/Components/Speech/SpeechWave.razor.cs
index 34c8de94b..310d4e8f4 100644
--- a/src/BootstrapBlazor/Components/Speech/SpeechWave.razor.cs
+++ b/src/BootstrapBlazor/Components/Speech/SpeechWave.razor.cs
@@ -30,10 +30,10 @@ public partial class SpeechWave : IDisposable
public Func? OnTimeout { get; set; }
///
- /// 获得/设置 总时长 默认 60 秒
+ /// 获得/设置 总时长 默认 60000 毫秒
///
[Parameter]
- public int TotalTimeSecond { get; set; } = 60;
+ public int TotalTime { get; set; } = 60000;
private TimeSpan UsedTimeSpan { get; set; }
@@ -48,7 +48,7 @@ public partial class SpeechWave : IDisposable
.AddClass("line", Show)
.Build();
- private string? TotalTimeSpanString => $"{TimeSpan.FromSeconds(TotalTimeSecond):mm\\:ss}";
+ private string? TotalTimeSpanString => $"{TimeSpan.FromMilliseconds(TotalTime):mm\\:ss}";
private string? UsedTimeSpanString => $"{UsedTimeSpan:mm\\:ss}";
@@ -90,18 +90,15 @@ public partial class SpeechWave : IDisposable
{
await Task.Delay(1000, Token.Token);
UsedTimeSpan = UsedTimeSpan.Add(TimeSpan.FromSeconds(1));
- if (UsedTimeSpan.TotalSeconds >= TotalTimeSecond)
+ if (UsedTimeSpan.TotalMilliseconds >= TotalTime)
{
Show = false;
if (OnTimeout != null)
{
- await OnTimeout();
+ _ = OnTimeout();
}
}
- if (Show)
- {
- await InvokeAsync(StateHasChanged);
- }
+ StateHasChanged();
}
catch
{
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/BootstrapBlazor.AzureSpeech.csproj b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/BootstrapBlazor.AzureSpeech.csproj
index febf4a49b..c3254f472 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/BootstrapBlazor.AzureSpeech.csproj
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/BootstrapBlazor.AzureSpeech.csproj
@@ -1,7 +1,7 @@
- 6.0.2
+ 6.0.3
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/RecognizerServiceExtensions.cs b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/RecognizerServiceExtensions.cs
index ba080845a..7e8aa11d1 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/RecognizerServiceExtensions.cs
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/RecognizerServiceExtensions.cs
@@ -14,14 +14,20 @@ public static class RecognizerServiceExtensions
///
///
///
- ///
- public static async Task RecognizeOnceAsync(this RecognizerService service, Func callback)
+ /// 默认 5000 毫秒后自动识别,设置 0 时禁用
+ public static async Task RecognizeOnceAsync(this RecognizerService service, Func callback, int? autoRecoginzerElapsedMilliseconds = null)
{
var option = new RecognizerOption()
{
MethodName = "bb_azure_speech_recognizeOnce",
Callback = callback
};
+
+ // 设置自动识别时间
+ if (autoRecoginzerElapsedMilliseconds.HasValue)
+ {
+ option.AutoRecoginzerElapsedMilliseconds = autoRecoginzerElapsedMilliseconds.Value;
+ }
await service.InvokeAsync(option);
}
@@ -30,14 +36,20 @@ public static class RecognizerServiceExtensions
///
///
///
- ///
- public static async Task RecognizeOnceAsync(this IRecognizerProvider provider, Func callback)
+ /// 默认 5000 毫秒后自动识别,设置 0 时禁用
+ public static async Task RecognizeOnceAsync(this IRecognizerProvider provider, Func callback, int? autoRecoginzerElapsedMilliseconds = null)
{
var option = new RecognizerOption()
{
MethodName = "bb_azure_speech_recognizeOnce",
Callback = callback
};
+
+ // 设置自动识别时间
+ if (autoRecoginzerElapsedMilliseconds.HasValue)
+ {
+ option.AutoRecoginzerElapsedMilliseconds = autoRecoginzerElapsedMilliseconds.Value;
+ }
await provider.InvokeAsync(option);
}
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/SynthesizerServiceExtensions.cs b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/SynthesizerServiceExtensions.cs
index e29a5687d..81c6ccdbc 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/SynthesizerServiceExtensions.cs
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Extensions/SynthesizerServiceExtensions.cs
@@ -16,7 +16,7 @@ public static class SynthesizerServiceExtensions
///
///
///
- public static async Task AzureSynthesizerOnceAsync(this SynthesizerService service, string? text, Func callback)
+ public static async Task SynthesizerOnceAsync(this SynthesizerService service, string? text, Func callback)
{
var option = new SynthesizerOption()
{
@@ -34,7 +34,7 @@ public static class SynthesizerServiceExtensions
///
///
///
- public static async Task AzureSynthesizerOnceAsync(this ISynthesizerProvider provider, string? text, Func callback)
+ public static async Task SynthesizerOnceAsync(this ISynthesizerProvider provider, string? text, Func callback)
{
var option = new SynthesizerOption()
{
@@ -51,7 +51,7 @@ public static class SynthesizerServiceExtensions
///
///
///
- public static async Task AzureCloseAsync(this SynthesizerService service, Func callback)
+ public static async Task CloseAsync(this SynthesizerService service, Func callback)
{
var option = new SynthesizerOption()
{
@@ -67,7 +67,7 @@ public static class SynthesizerServiceExtensions
///
///
///
- public static async Task AzureCloseAsync(this ISynthesizerProvider provider, Func callback)
+ public static async Task CloseAsync(this ISynthesizerProvider provider, Func callback)
{
var option = new SynthesizerOption()
{
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureRecognizerProvider.cs b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureRecognizerProvider.cs
index 0b833e872..8f0b7ad60 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureRecognizerProvider.cs
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureRecognizerProvider.cs
@@ -3,6 +3,7 @@
// Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using System.Net.Http.Json;
@@ -29,6 +30,8 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
private IMemoryCache Cache { get; }
+ private ILogger Logger { get; }
+
///
/// 构造函数
///
@@ -36,11 +39,13 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
///
///
///
- public AzureRecognizerProvider(IOptionsMonitor options, IJSRuntime runtime, IHttpClientFactory factory, IMemoryCache cache)
+ ///
+ public AzureRecognizerProvider(IOptionsMonitor options, IJSRuntime runtime, IHttpClientFactory factory, IMemoryCache cache, ILogger logger)
{
Cache = cache;
JSRuntime = runtime;
SpeechOption = options.CurrentValue;
+ Logger = logger;
Client = factory.CreateClient();
Client.BaseAddress = new Uri(string.Format(SpeechOption.AuthorizationTokenUrl, SpeechOption.Region));
if (SpeechOption.Timeout > 0)
@@ -57,21 +62,19 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
///
public async Task InvokeAsync(RecognizerOption option)
{
- if (string.IsNullOrEmpty(option.MethodName))
+ if (!string.IsNullOrEmpty(option.MethodName))
{
- throw new InvalidOperationException();
- }
-
- // 通过 SubscriptionKey 交换 Token
- var token = await ExchangeToken();
+ // 通过 SubscriptionKey 交换 Token
+ var token = await ExchangeToken();
- Option = option;
- if (Module == null)
- {
- Module = await JSRuntime.InvokeAsync("import", "./_content/BootstrapBlazor.AzureSpeech/js/speech.js");
+ Option = option;
+ if (Module == null)
+ {
+ Module = await JSRuntime.InvokeAsync("import", "./_content/BootstrapBlazor.AzureSpeech/js/speech.js");
+ }
+ Interop ??= DotNetObjectReference.Create(this);
+ await Module.InvokeVoidAsync(Option.MethodName, Interop, nameof(Callback), token, SpeechOption.Region, option.SpeechRecognitionLanguage, option.TargetLanguage, option.AutoRecoginzerElapsedMilliseconds);
}
- Interop ??= DotNetObjectReference.Create(this);
- await Module.InvokeVoidAsync(Option.MethodName, Interop, nameof(Callback), token, SpeechOption.Region, option.SpeechRecognitionLanguage, option.TargetLanguage);
}
private Task ExchangeToken() => Cache.GetOrCreateAsync(SpeechOption.SubscriptionKey, async entry =>
@@ -80,6 +83,8 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
var ret = "";
try
{
+ entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(50);
+ Logger.LogInformation($"request url: {url}");
var result = await Client.PostAsJsonAsync(url, "");
if (result.IsSuccessStatusCode)
{
@@ -89,14 +94,10 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(9);
}
}
- else
- {
- entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(50);
- }
}
- catch
+ catch (Exception ex)
{
-
+ Logger.LogError(ex, "ExchangeToken");
}
return ret;
});
@@ -110,6 +111,7 @@ public class AzureRecognizerProvider : IRecognizerProvider, IAsyncDisposable
[JSInvokable]
public async Task Callback(RecognizerStatus status, string result)
{
+ Logger.LogInformation($"RecognizerStatus: {status} Result: {result}");
if (Option.Callback != null)
{
await Option.Callback(status, result);
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureSynthesizerProvider.cs b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureSynthesizerProvider.cs
index 7b18c8254..c5a62209f 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureSynthesizerProvider.cs
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/Services/AzureSynthesizerProvider.cs
@@ -3,6 +3,7 @@
// Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using System.Net.Http.Json;
@@ -29,6 +30,8 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
private IMemoryCache Cache { get; }
+ private ILogger Logger { get; }
+
///
/// 构造函数
///
@@ -36,11 +39,13 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
///
///
///
- public AzureSynthesizerProvider(IOptionsMonitor options, IJSRuntime runtime, IHttpClientFactory factory, IMemoryCache cache)
+ ///
+ public AzureSynthesizerProvider(IOptionsMonitor options, IJSRuntime runtime, IHttpClientFactory factory, IMemoryCache cache, ILogger logger)
{
Cache = cache;
JSRuntime = runtime;
SpeechOption = options.CurrentValue;
+ Logger = logger;
Client = factory.CreateClient();
Client.BaseAddress = new Uri(string.Format(SpeechOption.AuthorizationTokenUrl, SpeechOption.Region));
if (SpeechOption.Timeout > 0)
@@ -51,7 +56,7 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
}
///
- ///
+ /// InvokeAsync 方法
///
///
///
@@ -83,6 +88,7 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
var ret = "";
try
{
+ Logger.LogInformation($"request url: {url}");
var result = await Client.PostAsJsonAsync(url, "");
if (result.IsSuccessStatusCode)
{
@@ -93,21 +99,22 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
}
}
}
- catch
+ catch (Exception ex)
{
-
+ Logger.LogError(ex, "ExchangeToken");
}
return ret;
});
///
- ///
+ /// Callback 回调方法 由 Javascript 调用
///
///
///
[JSInvokable]
public async Task Callback(SynthesizerStatus status)
{
+ Logger.LogInformation($"SynthesizerStatus: {status}");
if (Option.Callback != null)
{
await Option.Callback(status);
@@ -134,7 +141,7 @@ public class AzureSynthesizerProvider : ISynthesizerProvider, IAsyncDisposable
}
///
- ///
+ /// DisposeAsync 方法
///
///
public async ValueTask DisposeAsync()
diff --git a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/wwwroot/js/speech.js b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/wwwroot/js/speech.js
index a5a12cbf1..4d52b73f3 100644
--- a/src/Extensions/Components/BootstrapBlazor.AzureSpeech/wwwroot/js/speech.js
+++ b/src/Extensions/Components/BootstrapBlazor.AzureSpeech/wwwroot/js/speech.js
@@ -2,7 +2,7 @@
var synthesizer = undefined;
var player = undefined;
-export function bb_azure_speech_recognizeOnce(obj, method, token, region, recognitionLanguage, targetLanguage) {
+export function bb_azure_speech_recognizeOnce(obj, method, token, region, recognitionLanguage, targetLanguage, interval) {
var azure_recognizer = function () {
var speechConfig = SpeechSDK.SpeechTranslationConfig.fromAuthorizationToken(token, region);
speechConfig.speechRecognitionLanguage = recognitionLanguage;
@@ -18,9 +18,19 @@ export function bb_azure_speech_recognizeOnce(obj, method, token, region, recogn
obj.invokeMethodAsync(method, "Finished", successfulResult.privText);
}, function (err) {
console.log(err);
+ recognizer = undefined;
obj.invokeMethodAsync(method, "Error", err);
});
+ if (interval) {
+ var handler = window.setTimeout(function () {
+ window.clearTimeout(handler);
+ if (recognizer != undefined) {
+ recognizer.close();
+ recognizer = undefined;
+ }
+ }, interval);
+ }
};
BootstrapBlazorModules.addScript('_content/BootstrapBlazor.AzureSpeech/js/microsoft.cognitiveservices.speech.sdk.bundle.js');
@@ -58,7 +68,9 @@ export function bb_azure_speech_synthesizerOnce(obj, method, token, region, synt
function (err) {
console.log(err);
- synthesizer.close();
+ if (synthesizer != undefined) {
+ synthesizer.close();
+ }
synthesizer = undefined;
obj.invokeMethodAsync(method, "Error");
});
diff --git a/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/BootstrapBlazor.BaiduSpeech.csproj b/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/BootstrapBlazor.BaiduSpeech.csproj
index 97840aac6..f70b7bcd6 100644
--- a/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/BootstrapBlazor.BaiduSpeech.csproj
+++ b/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/BootstrapBlazor.BaiduSpeech.csproj
@@ -1,7 +1,7 @@
- 6.0.7
+ 6.0.8
diff --git a/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/Services/BaiduRecognizerProvider.cs b/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/Services/BaiduRecognizerProvider.cs
index 4345e142b..9b78f6e4a 100644
--- a/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/Services/BaiduRecognizerProvider.cs
+++ b/src/Extensions/Components/BootstrapBlazor.BaiduSpeech/Services/BaiduRecognizerProvider.cs
@@ -62,7 +62,6 @@ public class BaiduRecognizerProvider : IRecognizerProvider, IAsyncDisposable
}
Interop ??= DotNetObjectReference.Create(this);
await Module.InvokeVoidAsync(Option.MethodName, Interop, nameof(RecognizeCallback), Option.AutoRecoginzerElapsedMilliseconds);
- Logger.LogInformation($"{Option.MethodName}");
}
}
@@ -73,26 +72,30 @@ public class BaiduRecognizerProvider : IRecognizerProvider, IAsyncDisposable
public async Task RecognizeCallback(RecognizerStatus status, byte[]? bytes)
{
Logger.LogInformation($"RecognizerStatus: {status}");
- string data = "Error";
+ string data = "";
if (status == RecognizerStatus.Finished)
{
- var result = Client.Recognize(bytes, "wav", 16000);
- var err_no = result.Value("err_no");
- if (err_no == 0)
+ // 此处同步调用卡 UI 改为异步
+ await Task.Run(() =>
{
- var sb = new StringBuilder();
- var text = result["result"].ToArray();
- foreach (var item in text)
+ var result = Client.Recognize(bytes, "wav", 16000);
+ var err_no = result.Value("err_no");
+ if (err_no == 0)
{
- sb.Append(item.ToString());
+ var sb = new StringBuilder();
+ var text = result["result"].ToArray();
+ foreach (var item in text)
+ {
+ sb.Append(item.ToString());
+ }
+ data = sb.ToString();
+ Logger.LogInformation($"recognizer: {data}");
}
- data = sb.ToString();
- Logger.LogInformation($"recognizer: {data}");
- }
- else
- {
- Logger.LogError($"err_no: {err_no}");
- }
+ else
+ {
+ Logger.LogError($"err_no: {err_no}");
+ }
+ });
}
if (Option.Callback != null)
--
Gitee
From 30af17b3598dd4b003da37ce5c77cea789619ad6 Mon Sep 17 00:00:00 2001
From: Argo
Date: Fri, 13 May 2022 09:01:19 +0000
Subject: [PATCH 09/45] =?UTF-8?q?!2777=20feat(#I578CU):=20MultiSelect=20su?=
=?UTF-8?q?pport=20group=20feature=20*=20doc:=20=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=E7=A4=BA=E4=BE=8B=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95=E9=80=89?=
=?UTF-8?q?=E4=B8=AD=E9=97=AE=E9=A2=98=20*=20style:=20=E5=BE=AE=E8=B0=83?=
=?UTF-8?q?=E5=A4=9A=E9=80=89=E6=A1=86=E9=80=89=E4=B8=AD=E9=A1=B9=E8=83=8C?=
=?UTF-8?q?=E6=99=AF=E8=89=B2=20*=20doc:=20=E7=B2=BE=E7=AE=80=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=20*=20Merge=20branch=20'main'=20into=20docs-dialog=20?=
=?UTF-8?q?*=20chore:=20bump=20version=20to=206.6.7=20*=20doc:=20=E5=A2=9E?=
=?UTF-8?q?=E5=8A=A0=E5=88=86=E7=BB=84=E7=A4=BA=E4=BE=8B=20*=20doc:=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B5=84=E6=BA=90=E6=96=87=E4=BB=B6=20*=20do?=
=?UTF-8?q?c:=20=E5=A2=9E=E5=8A=A0=E7=A4=BA=E4=BE=8B=20*=20chore:=20bump?=
=?UTF-8?q?=20version=206.6.7-beta02=20*=20refactor:=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E4=BB=A3=E7=A0=81=20*=20feat:=20=E5=A2=9E=E5=8A=A0=E5=88=86?=
=?UTF-8?q?=E7=BB=84=E5=8A=9F=E8=83=BD=20*=20doc:=20=E6=9B=B4=E6=AD=A3=20f?=
=?UTF-8?q?ooter=20=E6=A0=B7=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Components/DataDialogComponent.razor | 2 +-
src/BootstrapBlazor.Shared/Locales/en.json | 2 +
src/BootstrapBlazor.Shared/Locales/zh.json | 2 +
.../Samples/MultiSelects.razor | 26 ++++++++-----
.../Samples/MultiSelects.razor.cs | 23 +++++++++++
src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +-
.../Components/Select/MultiSelect.css | 2 +-
.../Components/Select/MultiSelect.razor | 31 +++++++++------
.../Components/Select/Select.razor | 38 +++++++------------
.../css/bootstrap.blazor.bundle.min.css | 2 +-
10 files changed, 81 insertions(+), 49 deletions(-)
diff --git a/src/BootstrapBlazor.Shared/Components/DataDialogComponent.razor b/src/BootstrapBlazor.Shared/Components/DataDialogComponent.razor
index dd2cadbb9..a944e790e 100644
--- a/src/BootstrapBlazor.Shared/Components/DataDialogComponent.razor
+++ b/src/BootstrapBlazor.Shared/Components/DataDialogComponent.razor
@@ -15,7 +15,7 @@
-