All of this code relies on the output of one of my side projects named
Check out my new Twitter account (@blazorbits) for Blazor tips and tricks! Below you’ll see the Progress Telerik REPL (Read Evaluate Print Loop) for Blazor, select the Preview tab and watch the Blazor WebAssembly app perform a .NET restore and builds the app. Once the app loads, select a Natural voice from the voice selection control if it is available to you. If it’s not available to you, that’s not a big deal either. Select the Speak button and the app will speak the text you entered in the Text-to-speech control. You can also select the Stop button to stop the speech.
Explore the app source code
when you create your own REPL session you’re free to consume public NuGet packages, this app uses the
Blazor.SpeechSynthesis.WebAssembly NuGet package 📦.
Explore the Code tab thoroughly and look through the app’s source code. You’ll see that this app does the following:
- _Main.razor: The app’s main page, that showing a loading indicator and immediately navigates to the /speak route.
- TextToSpeech.razor: The page that renders the Text-to-speech text input element and the browser-native speech synthesis control buttons.
- TextToSpeech.razor.cs: The page’s code-behind that contains the
- Startup.cs: The app’s startup class that configures services, calling a source-generated dependency injection specific extension method named `AddSpeechServices.
ISpeechSynthesisService types. These are all from the
Blazor.SpeechSynthesis.WebAssembly NuGet package 📦. The
SpeechSynthesisVoice type is an array of
SpeechSynthesisVoice objects that represent the available voices on the user’s device. The
SpeechSynthesisUtterance type is a class that represents the text to be spoken and the voice to be used. The
ISpeechSynthesisService type is an interface that defines the
GetVoicesAsync and an in-process
Speak method that is synchronous.
Speak function takes a
SpeechSynthesisUtterance object and a callback function that is invoked when the speech is complete, delivering the total elapsed time in milliseconds.
There is also a way to listen for changes in the browser-native
ISpeechSynthesisService.OnVoicesChanged event and it will be invoked when the
voiceschanged event is fired. This is useful if you want to update the UI with the available voices. All of this functionality is source-generated by the
This project was originally written as part of a Microsoft hackathon. It’s been refined, but is still a brute-force effort and could stand to be optimized. As such I’m working to reimplement the parsing approach. It currently makes an HTTP request to a raw Github link with the lib.dom.d.ts file with all of the DOM type declarations in it. The file is itself, generated, and is over 18 thousand lines of code. It uses
Regex expressions to parse on-demand single hierarchical type dependency graphs as
readonly record struct values. These values were modeled as
Patent pending, not… ☹️
I was working with Stephen Toub (the patent lead for the .NET team), and we filed it for a patent. I was disappointed to learn that it wasn’t filed as the lawyers reviewed it and determined that it wasn’t patentable. I’m not sure why, but I’m glad to share it with you. I hope you find it useful. If you have any questions, please feel free to reach out to me:
The community is excited about this project, and I’m excited to see what you build with it. Here’s what some of the community members have said on Twitter:
@davidpine7 Hey man, I’m looking to use Blazorators to generate some JS APIs for me. Is there a way to point it to a .ts or .d.ts file and have it spit out the Blazor APIs that implement it?— Robert McLaws (@robertmclaws) April 2, 2022
Found the parser in the lib now. That is so cool! 😀 I will check it out. Seems like it would be easy to extend the existing code if some 'WebIDLParser' just has the same methods as your `LibDomParser`.— Kristoffer Strube (@KStrubeG) March 13, 2022
I love the TS bit!— Peter Morris #BlazorUniversity (@MrPeterLMorris) March 30, 2022
I love this project name. Blazorators, mount up!— Scott Addie (@Scott_Addie) March 25, 2022
I’m rewriting the TypeScript abstract syntax tree parser to C#, essentially porting it one-to-one. When this is done, the parsing will be much more accurate and flexible. Likewise, our friends over on Twitter, and some of the community members on YouTube have been kind to me as well. Thank you for your kind words, they mean the world to me.
This is a pretty amazing project. Hope this makes it into a serious project at Microsoft! Thank you!fieryscorpion
I think this package has a lot of potential. It makes the bridge between JS and C# in Blazor much less painful. I love it! Well done, David.Jiří Novotný