-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(WebSpeechSynthesizer): add WebSpeechSynthesizer service (#4135)
* refactor: 使用主构造函数 * feat: 增加 WebSpeech 服务 * feat: 增加 WebSpeechService 服务 * doc: 增加示例 * feat: 增加回调方法 * doc: 更新示例 * doc: 更新示例 * chore: bump version 8.8.4-beta07
- Loading branch information
Showing
9 changed files
with
227 additions
and
27 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/BootstrapBlazor.Server/Components/Samples/Speeches/WebSpeeches.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
@page "/speech/web-synthesizer" | ||
@inherits BootstrapComponentBase | ||
|
||
<h3>@Localizer["WebSpeechTitle"]</h3> | ||
<h4>@Localizer["WebSpeechSubTitle"]</h4> | ||
|
||
<DemoBlock Title="@Localizer["WebSpeechNormalTitle"]" | ||
Introduction="@Localizer["WebSpeechNormalIntro"]" | ||
Name="Normal"> | ||
<div class="row"> | ||
<div class="col-12 col-sm-6"> | ||
<textarea @bind="_text" rows="6"></textarea> | ||
</div> | ||
<div class="col-12 col-sm-6 text-center"> | ||
<SpeechWave Show="_star" ShowUsedTime="false" class="my-3"></SpeechWave> | ||
<Button Text="@_buttonText" OnClickWithoutRender="OnStart" IsAsync="true" Icon="fa-fw fa-solid fa-microphone"></Button> | ||
</div> | ||
</div> | ||
</DemoBlock> |
52 changes: 52 additions & 0 deletions
52
src/BootstrapBlazor.Server/Components/Samples/Speeches/WebSpeeches.razor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright (c) Argo Zhang ([email protected]). All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
// Website: https://www.blazor.zone or https://argozhang.github.io/ | ||
|
||
using Microsoft.AspNetCore.Components.Forms; | ||
|
||
namespace BootstrapBlazor.Server.Components.Samples.Speeches; | ||
|
||
/// <summary> | ||
/// WebSpeech 组件示例代码 | ||
/// </summary> | ||
public partial class WebSpeeches | ||
{ | ||
[Inject, NotNull] | ||
private WebSpeechService? WebSpeechService { get; set; } | ||
|
||
[Inject, NotNull] | ||
private IStringLocalizer<WebSpeeches>? Localizer { get; set; } | ||
|
||
private bool _star; | ||
private string? _text; | ||
private string? _buttonText = "开始合成"; | ||
private WebSpeechSynthesizer _entry = default!; | ||
private TaskCompletionSource? _tcs; | ||
|
||
private async Task OnStart() | ||
{ | ||
if (!string.IsNullOrEmpty(_text)) | ||
{ | ||
if (_entry == null) | ||
{ | ||
_entry = await WebSpeechService.CreateSynthesizerAsync(); | ||
_entry.OnEndAsync = SpeakAsync; | ||
} | ||
_tcs ??= new(); | ||
_star = true; | ||
StateHasChanged(); | ||
|
||
await _entry.SpeakAsync(_text, "zh-CN"); | ||
await _tcs.Task; | ||
_star = false; | ||
_tcs = null; | ||
StateHasChanged(); | ||
} | ||
} | ||
|
||
private Task SpeakAsync() | ||
{ | ||
_tcs?.TrySetResult(); | ||
return Task.CompletedTask; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright (c) Argo Zhang ([email protected]). All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
// Website: https://www.blazor.zone or https://argozhang.github.io/ | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
namespace BootstrapBlazor.Components; | ||
|
||
/// <summary> | ||
/// Web Speech 服务 | ||
/// </summary> | ||
public class WebSpeechService(IJSRuntime runtime, IComponentIdGenerator ComponentIdGenerator, ILogger<WebSpeechService> logger) | ||
{ | ||
private JSModule? Module { get; set; } | ||
|
||
/// <summary> | ||
/// 语音合成方法 | ||
/// </summary> | ||
/// <returns></returns> | ||
public async Task<WebSpeechSynthesizer> CreateSynthesizerAsync() | ||
{ | ||
if (Module == null) | ||
{ | ||
var moduleName = "./_content/BootstrapBlazor/modules/speech.js"; | ||
logger.LogInformation("load module {moduleName}", moduleName); | ||
Module = await runtime.LoadModule(moduleName); | ||
} | ||
return new WebSpeechSynthesizer(Module, ComponentIdGenerator); | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
src/BootstrapBlazor/Components/Speech/WebSpeechSynthesizer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright (c) Argo Zhang ([email protected]). All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
// Website: https://www.blazor.zone or https://argozhang.github.io/ | ||
|
||
namespace BootstrapBlazor.Components; | ||
|
||
/// <summary> | ||
/// WebSpeechSynthesizer 类 | ||
/// </summary> | ||
public class WebSpeechSynthesizer(JSModule module, IComponentIdGenerator componentIdGenerator) | ||
{ | ||
private DotNetObjectReference<WebSpeechSynthesizer>? _interop; | ||
|
||
private string? _id; | ||
|
||
/// <summary> | ||
/// 获得/设置 朗读结束回调方法 默认 null | ||
/// </summary> | ||
public Func<Task>? OnEndAsync { get; set; } | ||
|
||
/// <summary> | ||
/// 开始朗读方法 | ||
/// </summary> | ||
/// <param name="text"></param> | ||
/// <param name="lang"></param> | ||
public async Task SpeakAsync(string? text, string? lang = null) | ||
{ | ||
_id = componentIdGenerator.Generate(this); | ||
_interop = DotNetObjectReference.Create(this); | ||
await module.InvokeVoidAsync("speak", _id, _interop, new { text, lang }); | ||
} | ||
|
||
/// <summary> | ||
/// 暂停朗读方法 | ||
/// </summary> | ||
/// <returns></returns> | ||
public async Task Pause() | ||
{ | ||
await module.InvokeVoidAsync("pause", _id); | ||
} | ||
|
||
/// <summary> | ||
/// 恢复朗读方法 | ||
/// </summary> | ||
/// <returns></returns> | ||
public async Task Resume() | ||
{ | ||
await module.InvokeVoidAsync("resume", _id); | ||
} | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <returns></returns> | ||
[JSInvokable] | ||
public async Task OnError() | ||
{ | ||
await Task.CompletedTask; | ||
} | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <returns></returns> | ||
[JSInvokable] | ||
public async Task OnEnd() | ||
{ | ||
if (OnEndAsync != null) | ||
{ | ||
await OnEndAsync(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <returns></returns> | ||
[JSInvokable] | ||
public async Task OnSpeaking() | ||
{ | ||
await Task.CompletedTask; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import Data from "./data.js" | ||
|
||
export function speak(id, invoke, option) { | ||
const synth = window.speechSynthesis; | ||
if (synth.speaking) { | ||
console.error("speechSynthesis.speaking"); | ||
invoke.invokeMethodAsync("OnSpeaking"); | ||
return; | ||
} | ||
const { text, lang } = option; | ||
if (text !== "") { | ||
const utter = new SpeechSynthesisUtterance(text); | ||
if (lang) { | ||
utter.lang = lang; | ||
} | ||
|
||
utter.onend = () => { | ||
invoke.invokeMethodAsync("OnEnd"); | ||
}; | ||
|
||
utter.onerror = e => { | ||
console.error("SpeechSynthesisUtterance.onerror", e); | ||
invoke.invokeMethodAsync("OnError"); | ||
}; | ||
synth.speak(utter); | ||
} | ||
} | ||
|
||
export function pause(id) { | ||
|
||
} | ||
|
||
export function resume(id) { | ||
|
||
} |