title
Text To Speech & Synthesis App - JavaScript & Web Speech API
description
In this video we will build a text synthesis application using vanilla JavaScript and the web speech API. We will also use Bootstrap 4 to create the UI.
Sponsor:
DevMountain Bootcamp - https://goo.gl/6q0dEa
Code For This Project:
https://github.com/bradtraversy/type-n-speak
App Demo:
https://bradtraversy.github.io/type-n-speak/
💖 Become a Patron: Show support & get perks!
http://www.patreon.com/traversymedia
Website & Udemy Courses
http://www.traversymedia.com
Follow Traversy Media:
https://www.facebook.com/traversymedia
https://www.twitter.com/traversymedia
https://www.instagram.com/traversymedia
More About The Web Speech API:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API
detail
{'title': 'Text To Speech & Synthesis App - JavaScript & Web Speech API', 'heatmap': [{'end': 350.789, 'start': 288.489, 'weight': 0.85}, {'end': 826.749, 'start': 792.439, 'weight': 0.858}, {'end': 1378.612, 'start': 1347.748, 'weight': 1}, {'end': 2147.289, 'start': 2090.263, 'weight': 0.821}], 'summary': 'Tutorial demonstrates building a vanilla javascript text-to-speech app using the web speech api, allowing customization of speech rate, pitch, voice, languages, and accents, along with ui form creation, speech synthesis api implementation, voice selection, and troubleshooting, resulting in successful functionality and testing.', 'chapters': [{'end': 516.722, 'segs': [{'end': 49.922, 'src': 'embed', 'start': 23.479, 'weight': 2, 'content': [{'end': 33.348, 'text': "guys, in this video we're going to be building a vanilla javascript text-to-speech application and we're not going to use any third-party libraries or anything like that.", 'start': 23.479, 'duration': 9.869}, {'end': 37.832, 'text': "what we're going to use is the web speech api, which is actually a browser-based api.", 'start': 33.348, 'duration': 4.484}, {'end': 39.013, 'text': 'i meant to have it up here.', 'start': 37.832, 'duration': 1.181}, {'end': 41.696, 'text': "let's see web speech api.", 'start': 39.013, 'duration': 2.683}, {'end': 49.922, 'text': "so this is the mdn site for it and it says experimental technology, but it's pretty compatible if you look here.", 'start': 43.037, 'duration': 6.885}], 'summary': 'Building a vanilla javascript text-to-speech app using web speech api.', 'duration': 26.443, 'max_score': 23.479, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G823479.jpg'}, {'end': 89.441, 'src': 'embed', 'start': 63.172, 'weight': 0, 'content': [{'end': 69.974, 'text': "So I've tested it on Mozilla, Safari and Chrome and it works flawlessly on all of them.", 'start': 63.172, 'duration': 6.802}, {'end': 71.914, 'text': "So that's what we'll be building.", 'start': 70.554, 'duration': 1.36}, {'end': 81.016, 'text': 'And basically, we can put whatever we want in here for it to say, we can change the rate, which is the speed of of the, the,', 'start': 72.414, 'duration': 8.602}, {'end': 83.237, 'text': 'the speak and then the pitch as well.', 'start': 81.016, 'duration': 2.221}, {'end': 86.999, 'text': 'OK, and then these voices we can fetch through the API.', 'start': 83.817, 'duration': 3.182}, {'end': 89.441, 'text': "And there's actually like different languages.", 'start': 87.459, 'duration': 1.982}], 'summary': 'Tested speech api on mozilla, safari, and chrome, works flawlessly. can change rate and pitch. can fetch voices through api.', 'duration': 26.269, 'max_score': 63.172, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G863172.jpg'}, {'end': 350.789, 'src': 'heatmap', 'start': 288.489, 'weight': 0.85, 'content': [{'end': 295.432, 'text': "i'm going to go ahead and close up this sidebar and let's see we'll change the title here to type.", 'start': 288.489, 'duration': 6.943}, {'end': 300.154, 'text': "we'll do type and speak and then we're going to need to include bootstrap.", 'start': 295.432, 'duration': 4.722}, {'end': 304.036, 'text': "so let's head over to getbootstrap.com.", 'start': 300.154, 'duration': 3.882}, {'end': 307.317, 'text': "we'll say get started and we want to grab the link right here.", 'start': 304.036, 'duration': 3.281}, {'end': 315.507, 'text': "Paste that in and then we'll grab the three JavaScript dependencies here, because I think you need them for the slider.", 'start': 308.783, 'duration': 6.724}, {'end': 317.789, 'text': "I'm not positive on that, but I think you do.", 'start': 315.747, 'duration': 2.042}, {'end': 319.03, 'text': "So we'll paste those in.", 'start': 317.909, 'duration': 1.121}, {'end': 324.953, 'text': 'And of course, we want to put a link to our script source.', 'start': 319.41, 'duration': 5.543}, {'end': 331.758, 'text': 'We want to put a script that points to js main.js, which is our custom JavaScript file.', 'start': 325.173, 'duration': 6.585}, {'end': 333.539, 'text': "All right, we'll save that.", 'start': 332.498, 'duration': 1.041}, {'end': 337.821, 'text': 'I am using the prettier extension for VS Code, so it does clean up my code.', 'start': 333.559, 'duration': 4.262}, {'end': 342.164, 'text': "If I go ahead and I move this over and save, it's going to format it for me.", 'start': 337.861, 'duration': 4.303}, {'end': 350.789, 'text': "I'm also using Live Server, so I can go open with Live Server, and it'll open the application in the browser.", 'start': 342.644, 'duration': 8.145}], 'summary': 'Setting up sidebar with type and speak title, including bootstrap dependencies and custom javascript file.', 'duration': 62.3, 'max_score': 288.489, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8288489.jpg'}], 'start': 7.059, 'title': 'Building vanilla javascript text-to-speech app', 'summary': 'Covers building a vanilla javascript text-to-speech application using the web speech api, compatible with chrome, edge, firefox, and safari, allowing customization of speech rate, pitch, voice, languages, and accents.', 'chapters': [{'end': 516.722, 'start': 7.059, 'title': 'Building vanilla javascript text-to-speech app', 'summary': 'Covers building a vanilla javascript text-to-speech application using the web speech api, which is compatible with chrome, edge, firefox, and safari, and allows for customization of speech rate, pitch, and voice, as well as the use of different languages and accents.', 'duration': 509.663, 'highlights': ['The web speech API is compatible with Chrome, Edge, Firefox, and Safari, allowing for a seamless experience across different browsers. The speaker tested the web speech API on Mozilla, Safari, and Chrome, and it worked flawlessly on all of them, indicating its compatibility with major browsers.', 'The speech rate, pitch, and voice can be customized, with the ability to fetch different voices through the API, and support for different languages and accents. The application allows users to customize speech rate, pitch, and voice, and provides the capability to fetch different voices through the API, supporting various languages and accents.', 'The built application allows for a visual representation of the speech through a waveform image that changes as the speech is being generated. The speaker used a GIF image as a waveform to visually represent the speech, providing a dynamic and engaging visual element to the text-to-speech application.']}], 'duration': 509.663, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G87059.jpg', 'highlights': ['The web speech API is compatible with Chrome, Edge, Firefox, and Safari, ensuring a seamless experience across different browsers.', 'The application allows users to customize speech rate, pitch, and voice, supporting various languages and accents.', 'The built application includes a visual representation of the speech through a dynamic waveform image.']}, {'end': 792.299, 'segs': [{'end': 547.5, 'src': 'embed', 'start': 517.663, 'weight': 5, 'content': [{'end': 518.683, 'text': "But that's another video.", 'start': 517.663, 'duration': 1.02}, {'end': 521.726, 'text': "So let's go ahead and add another form group.", 'start': 518.764, 'duration': 2.962}, {'end': 528.81, 'text': "So we'll say form group and this is going to be the the rate slider.", 'start': 524.708, 'duration': 4.102}, {'end': 538.577, 'text': "Actually, one thing I want to do with this text area is add a placeholder placeholder and we'll just say type anything.", 'start': 529.171, 'duration': 9.406}, {'end': 541.628, 'text': 'Of course, you could put whatever you want.', 'start': 540.365, 'duration': 1.263}, {'end': 543.392, 'text': "You don't have to do exactly what I do.", 'start': 541.648, 'duration': 1.744}, {'end': 547.5, 'text': "And then in here, we're going to have a label, first of all.", 'start': 544.193, 'duration': 3.307}], 'summary': 'Adding form group and placeholder to text area.', 'duration': 29.837, 'max_score': 517.663, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8517663.jpg'}, {'end': 704.859, 'src': 'embed', 'start': 598.521, 'weight': 0, 'content': [{'end': 605.047, 'text': "And then the step, which is like each time you move it, how, how much does it move? It's going to be 0.1.", 'start': 598.521, 'duration': 6.526}, {'end': 606.908, 'text': "Okay Let's save that.", 'start': 605.047, 'duration': 1.861}, {'end': 607.669, 'text': 'And there it is.', 'start': 607.088, 'duration': 0.581}, {'end': 612.633, 'text': "Now, as it is, you can't see what the rate is.", 'start': 608.309, 'duration': 4.324}, {'end': 618.979, 'text': 'I mean, you can see the place where it is here, but I want it to show over here what the rate actually is.', 'start': 612.653, 'duration': 6.326}, {'end': 624.544, 'text': "So under the label, I'm going to put a div with the ID of rate-div.", 'start': 619.519, 'duration': 5.025}, {'end': 627.587, 'text': 'value OK.', 'start': 627.026, 'duration': 0.561}, {'end': 635.559, 'text': "So the rate value and it's going to be one by default because you can see I said value to one.", 'start': 628.929, 'duration': 6.63}, {'end': 641.307, 'text': "But in the JavaScript we'll make it so that this will basically echo whatever whatever we set it to.", 'start': 635.939, 'duration': 5.368}, {'end': 645.051, 'text': "Okay, and let's give this a couple of bootstrap classes.", 'start': 642.168, 'duration': 2.883}, {'end': 650.577, 'text': "So we want badge and let's do badge primary to make it that blue color.", 'start': 645.111, 'duration': 5.466}, {'end': 651.618, 'text': 'All right.', 'start': 651.318, 'duration': 0.3}, {'end': 657.684, 'text': 'And then one more class is I want to do float right just to quickly float it to the right.', 'start': 651.678, 'duration': 6.006}, {'end': 663.191, 'text': "So, yeah, I mean, I don't understand why people bash UI frameworks.", 'start': 658.685, 'duration': 4.506}, {'end': 666.836, 'text': 'So the next one is going to be the pitch, which is going to be very similar.', 'start': 664.072, 'duration': 2.764}, {'end': 674.005, 'text': "So I'm going to copy this whole form group right here and paste that in and we'll change this to pitch.", 'start': 666.856, 'duration': 7.149}, {'end': 685.049, 'text': "We'll change the label text to pitch and this and the ID both to pitch.", 'start': 676.027, 'duration': 9.022}, {'end': 687.39, 'text': 'And I did a control D.', 'start': 686.17, 'duration': 1.22}, {'end': 694.432, 'text': 'If you select something and you want the next value that matches it, you just do a control D and then you can change it to whatever you want.', 'start': 687.39, 'duration': 7.042}, {'end': 695.912, 'text': 'All right.', 'start': 695.572, 'duration': 0.34}, {'end': 697.353, 'text': "So let's see.", 'start': 696.072, 'duration': 1.281}, {'end': 698.775, 'text': 'The one is going to stay.', 'start': 697.454, 'duration': 1.321}, {'end': 700.616, 'text': 'Value one is going to stay.', 'start': 699.135, 'duration': 1.481}, {'end': 703.538, 'text': "Only thing we're going to change here is the minimum.", 'start': 700.976, 'duration': 2.562}, {'end': 704.859, 'text': 'I want to be zero.', 'start': 703.598, 'duration': 1.261}], 'summary': 'Updating ui with rate and pitch values, rate set to 0.1', 'duration': 106.338, 'max_score': 598.521, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8598521.jpg'}, {'end': 760.609, 'src': 'embed', 'start': 729.281, 'weight': 4, 'content': [{'end': 734.327, 'text': "We can actually fetch them using the API and then we're going to insert them using JavaScript.", 'start': 729.281, 'duration': 5.046}, {'end': 736.15, 'text': 'But we do need at least the element.', 'start': 734.388, 'duration': 1.762}, {'end': 739.193, 'text': "So I'm going to do a select and we're going to call this voice.", 'start': 736.59, 'duration': 2.603}, {'end': 743.917, 'text': 'dash select ID voice select.', 'start': 740.515, 'duration': 3.402}, {'end': 745.358, 'text': "You don't need a name.", 'start': 744.558, 'duration': 0.8}, {'end': 750.422, 'text': 'We do however want some classes to make this look good.', 'start': 747.22, 'duration': 3.202}, {'end': 759.328, 'text': "So it's a class form control and let's do form control large as well.", 'start': 751.182, 'duration': 8.146}, {'end': 760.609, 'text': 'All right.', 'start': 759.348, 'duration': 1.261}], 'summary': 'Fetching data using api, inserting with javascript, and adding classes for form control and large size.', 'duration': 31.328, 'max_score': 729.281, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8729281.jpg'}], 'start': 517.663, 'title': 'Ui form creation and customization', 'summary': 'Discusses adding a rate slider with a range of 0.5 to 2, a default value of 1, and a step of 0.1, along with a placeholder for a text area, and styling elements using bootstrap classes. it also details the process of creating a form for ui customization, including floating elements, copy-pasting, and specifying attributes such as minimum and maximum values, as well as the use of api to fetch and insert data using javascript.', 'chapters': [{'end': 651.618, 'start': 517.663, 'title': 'Adding rate slider and placeholder', 'summary': 'Discusses adding a rate slider with a range of 0.5 to 2, a default value of 1, and a step of 0.1, along with a placeholder for a text area, and styling elements using bootstrap classes.', 'duration': 133.955, 'highlights': ['Adding a rate slider with a range of 0.5 to 2, a default value of 1, and a step of 0.1. The input slider is defined with a range from 0.5 to 2, a default value of 1, and a step of 0.1, allowing for specific rate selection.', "Adding a placeholder for a text area. A placeholder 'type anything' is added to the text area to provide guidance for user input.", "Styling elements using Bootstrap classes. Bootstrap classes like 'badge' and 'badge primary' are applied to the rate display to enhance visual appearance."]}, {'end': 792.299, 'start': 651.678, 'title': 'Ui form creation and customization', 'summary': 'Details the process of creating a form for ui customization, including floating elements, copy-pasting, and specifying attributes such as minimum and maximum values, as well as the use of api to fetch and insert data using javascript.', 'duration': 140.621, 'highlights': ['The chapter explains the process of creating a form for UI customization, including floating elements, copy-pasting, and specifying attributes such as minimum and maximum values.', 'The transcript discusses using an API to fetch and insert data using JavaScript for the select list of voices in the form.', 'Demonstrates the use of control D for selecting and modifying values, such as changing the label text and ID for the pitch.', 'Details the use of Bootstrap classes to style form elements, including adding classes for buttons and select lists.']}], 'duration': 274.636, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8517663.jpg', 'highlights': ['Adding a rate slider with a range of 0.5 to 2, a default value of 1, and a step of 0.1.', 'The chapter explains the process of creating a form for UI customization, including floating elements, copy-pasting, and specifying attributes such as minimum and maximum values.', 'Demonstrates the use of control D for selecting and modifying values, such as changing the label text and ID for the pitch.', "Styling elements using Bootstrap classes. Bootstrap classes like 'badge' and 'badge primary' are applied to the rate display to enhance visual appearance.", 'The transcript discusses using an API to fetch and insert data using JavaScript for the select list of voices in the form.', "Adding a placeholder for a text area. A placeholder 'type anything' is added to the text area to provide guidance for user input."]}, {'end': 1122.846, 'segs': [{'end': 854.105, 'src': 'heatmap', 'start': 792.439, 'weight': 3, 'content': [{'end': 794.601, 'text': 'So we could do submit.', 'start': 792.439, 'duration': 2.162}, {'end': 795.502, 'text': "That's what I did have.", 'start': 794.621, 'duration': 0.881}, {'end': 802.067, 'text': "Let's do speak or we'll say speak it and save.", 'start': 795.542, 'duration': 6.525}, {'end': 805.223, 'text': 'OK So notice the select list is blank.', 'start': 803.041, 'duration': 2.182}, {'end': 805.884, 'text': "That's fine.", 'start': 805.263, 'duration': 0.621}, {'end': 808.286, 'text': "We're actually going to fill that using JavaScript.", 'start': 805.924, 'duration': 2.362}, {'end': 809.167, 'text': "So that's it.", 'start': 808.707, 'duration': 0.46}, {'end': 810.448, 'text': "That's it for the interface.", 'start': 809.227, 'duration': 1.221}, {'end': 813.712, 'text': "We shouldn't have to do anything else in the HTML.", 'start': 811.069, 'duration': 2.643}, {'end': 817.135, 'text': "So now we're going to move on to our main JS file.", 'start': 813.732, 'duration': 3.403}, {'end': 826.749, 'text': 'All right, so the way that we access the speech synthesis API is window.', 'start': 818.544, 'duration': 8.205}, {'end': 830.492, 'text': "We don't have to use window, but I'm just going to put it anyway.", 'start': 828.09, 'duration': 2.402}, {'end': 834.094, 'text': 'And then speech synthesis.', 'start': 830.632, 'duration': 3.462}, {'end': 841.279, 'text': "And what I'll do here is set a variable called synth equal to that.", 'start': 834.675, 'duration': 6.604}, {'end': 843.24, 'text': 'So that way we can use this variable.', 'start': 841.419, 'duration': 1.821}, {'end': 847.804, 'text': "Let's actually put a comment here, and I'm going to say init.", 'start': 844.241, 'duration': 3.563}, {'end': 854.105, 'text': 'Speech synth API.', 'start': 851.074, 'duration': 3.031}], 'summary': 'Using javascript to access and initialize the speech synthesis api.', 'duration': 35.561, 'max_score': 792.439, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8792439.jpg'}, {'end': 981.243, 'src': 'embed', 'start': 926.397, 'weight': 1, 'content': [{'end': 937.7, 'text': "So we need to fetch the voices using the API, and I'm actually going to initialize just an empty array here called voices.", 'start': 926.397, 'duration': 11.303}, {'end': 942.881, 'text': "And then we're going to create a function called get voices.", 'start': 938.88, 'duration': 4.001}, {'end': 947.442, 'text': "I'm going to use an arrow function, but you guys can go ahead and do this if you want.", 'start': 943.341, 'duration': 4.101}, {'end': 950.203, 'text': "If you're not comfortable with arrow functions, you can do that.", 'start': 947.642, 'duration': 2.561}, {'end': 960.81, 'text': "But what I'll do is we'll say const get voices and to turn it to an arrow function we just put an equal sign here and an arrow here.", 'start': 951.023, 'duration': 9.787}, {'end': 963.291, 'text': "Okay because I don't know I just want to keep it ES6.", 'start': 960.83, 'duration': 2.461}, {'end': 966.694, 'text': "So in here we're going to say voices.", 'start': 963.311, 'duration': 3.383}, {'end': 981.243, 'text': "So we're going to take that voices variable above and we're going to set it to synth, which reaches into the speech synthesis API,", 'start': 970.356, 'duration': 10.887}], 'summary': 'Initialize an empty array called voices and create a function to fetch voices using the api.', 'duration': 54.846, 'max_score': 926.397, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8926397.jpg'}, {'end': 1042.019, 'src': 'embed', 'start': 1012.336, 'weight': 0, 'content': [{'end': 1017.458, 'text': 'You would figure this would give us the voices but this is actually called a syncret asynchronously.', 'start': 1012.336, 'duration': 5.122}, {'end': 1024.28, 'text': 'So we have to wait for an event called on voices changed.', 'start': 1018.878, 'duration': 5.402}, {'end': 1036.123, 'text': 'OK And the way that how I figured this out was searching for what I say web speech API get voices empty.', 'start': 1024.96, 'duration': 11.163}, {'end': 1042.019, 'text': "So right here I know this is really small but let's see.", 'start': 1038.415, 'duration': 3.604}], 'summary': 'Using the web speech api to get voices asynchronously by waiting for the event on voices changed.', 'duration': 29.683, 'max_score': 1012.336, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81012336.jpg'}], 'start': 792.439, 'title': 'Speech synthesis api and voice creation', 'summary': 'Covers implementing the speech synthesis api, including accessing and initializing the api, and creating a function to fetch voices, resolving the issue of getting empty array of voices by setting up an event listener for onvoiceschanged.', 'chapters': [{'end': 899.022, 'start': 792.439, 'title': 'Speech synthesis api implementation', 'summary': 'Covers the implementation of the speech synthesis api, including accessing the api, initializing the api, and grabbing dom elements using query selectors and ids.', 'duration': 106.583, 'highlights': ['The chapter covers the implementation of the Speech Synthesis API, including accessing the API, initializing the API, and grabbing DOM elements using query selectors and IDs.']}, {'end': 1122.846, 'start': 899.902, 'title': 'Creating and fetching voices', 'summary': 'Discusses creating a function to fetch voices from the speech synthesis api, demonstrating the process of obtaining voices and the need to set up an event listener for onvoiceschanged, which resolves the issue of getting empty array of voices.', 'duration': 222.944, 'highlights': ['Creating a function to fetch voices from the speech synthesis API The chapter explains the process of creating a function called get voices to fetch voices from the speech synthesis API.', 'Demonstrating the process of obtaining voices It is shown that the process of obtaining voices from the speech synthesis API involves setting the voices variable using synth.getVoices.', 'The need to set up an event listener for onVoicesChanged The chapter highlights the importance of setting up an event listener for onVoicesChanged to resolve the issue of getting an empty array of voices.']}], 'duration': 330.407, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G8792439.jpg', 'highlights': ['The need to set up an event listener for onVoicesChanged to resolve the issue of getting an empty array of voices', 'Creating a function to fetch voices from the speech synthesis API', 'Demonstrating the process of obtaining voices from the speech synthesis API involves setting the voices variable using synth.getVoices', 'The chapter covers the implementation of the Speech Synthesis API, including accessing the API, initializing the API, and grabbing DOM elements using query selectors and IDs']}, {'end': 1656.413, 'segs': [{'end': 1200.352, 'src': 'embed', 'start': 1155.012, 'weight': 0, 'content': [{'end': 1157.533, 'text': 'OK, so our select list is blank right now.', 'start': 1155.012, 'duration': 2.521}, {'end': 1162.756, 'text': 'we want an option for each voice, so we could look through this a few different ways.', 'start': 1157.533, 'duration': 5.223}, {'end': 1163.796, 'text': 'like I said, I like to.', 'start': 1162.756, 'duration': 1.04}, {'end': 1165.377, 'text': "I'm going to keep this a little more modern.", 'start': 1163.796, 'duration': 1.581}, {'end': 1167.198, 'text': "I'm not going to use like a for loop or anything.", 'start': 1165.377, 'duration': 1.821}, {'end': 1168.359, 'text': "I'm going to use a for each.", 'start': 1167.198, 'duration': 1.161}, {'end': 1172.441, 'text': "so I'm going to say voices dot for each.", 'start': 1168.359, 'duration': 4.082}, {'end': 1178.092, 'text': "And for each one, we'll call it a voice and we'll use an arrow here.", 'start': 1174.529, 'duration': 3.563}, {'end': 1186.4, 'text': 'OK, so this is looping through all the voices and we want to create an option element.', 'start': 1178.112, 'duration': 8.288}, {'end': 1190.984, 'text': 'OK, because we can create DOM elements right from the JavaScript.', 'start': 1186.42, 'duration': 4.564}, {'end': 1194.727, 'text': "So the way that we're going to do that is create a variable.", 'start': 1192.065, 'duration': 2.662}, {'end': 1200.352, 'text': "We'll call it option and we'll set that equal to document dot create element.", 'start': 1194.767, 'duration': 5.585}], 'summary': 'Using javascript to create an option for each voice in a select list without using a for loop.', 'duration': 45.34, 'max_score': 1155.012, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81155012.jpg'}, {'end': 1301.578, 'src': 'embed', 'start': 1265.382, 'weight': 4, 'content': [{'end': 1270.004, 'text': 'Okay, so that should work.', 'start': 1265.382, 'duration': 4.622}, {'end': 1279.188, 'text': "Yeah, so object text content, so we'll have the name, and then we'll have the language in parentheses.", 'start': 1274.266, 'duration': 4.922}, {'end': 1289.061, 'text': "All right, under that, let's do You have to set needed option attributes.", 'start': 1280.269, 'duration': 8.792}, {'end': 1294.448, 'text': 'Okay, so there actually needs to be some special data attributes for each option.', 'start': 1290.423, 'duration': 4.025}, {'end': 1297.032, 'text': "There's going to be data name and data lang.", 'start': 1294.469, 'duration': 2.563}, {'end': 1301.578, 'text': 'So we can say option.setAttribute.', 'start': 1297.553, 'duration': 4.025}], 'summary': 'Creating object text content with name and language attributes for options.', 'duration': 36.196, 'max_score': 1265.382, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81265382.jpg'}, {'end': 1378.612, 'src': 'heatmap', 'start': 1335.822, 'weight': 7, 'content': [{'end': 1338.724, 'text': 'We define that up here.', 'start': 1335.822, 'duration': 2.902}, {'end': 1340.965, 'text': 'So right here, voice select.', 'start': 1339.524, 'duration': 1.441}, {'end': 1346.147, 'text': 'And we want to append child.', 'start': 1341.825, 'duration': 4.322}, {'end': 1347.628, 'text': "Remember, we're still within the loop.", 'start': 1346.187, 'duration': 1.441}, {'end': 1352.39, 'text': "So we're just taking each iteration and we're going to append the option.", 'start': 1347.748, 'duration': 4.642}, {'end': 1357.396, 'text': 'Okay, and I think that should do it.', 'start': 1353.79, 'duration': 3.606}, {'end': 1359.159, 'text': "Let's save this, and there we go.", 'start': 1357.456, 'duration': 1.703}, {'end': 1361.583, 'text': "If we look at our select list, now it's full.", 'start': 1359.179, 'duration': 2.404}, {'end': 1368.413, 'text': "Okay, it's full of all those voices, which are all coming from synth.getVoices.", 'start': 1361.603, 'duration': 6.81}, {'end': 1375.171, 'text': "So now that we've done that, let's start to work on the actual speech.", 'start': 1370.089, 'duration': 5.082}, {'end': 1378.612, 'text': "So I'm going to go down here and let's put a comment.", 'start': 1375.831, 'duration': 2.781}], 'summary': 'Code iterates through voices to populate select list with synth.getvoices data.', 'duration': 32.591, 'max_score': 1335.822, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81335822.jpg'}, {'end': 1430.095, 'src': 'embed', 'start': 1399.245, 'weight': 5, 'content': [{'end': 1401.565, 'text': "So we're going to skip that for now.", 'start': 1399.245, 'duration': 2.32}, {'end': 1409.648, 'text': 'First thing I want to do is and this is going to run when we click speak or speak it when we click the button.', 'start': 1401.625, 'duration': 8.023}, {'end': 1417.371, 'text': "It's also going to run as soon as we choose a person or a voice because I want it to run again with that voice.", 'start': 1409.688, 'duration': 7.683}, {'end': 1424.373, 'text': "So we need we need to check to make sure that it's not speaking when we click it.", 'start': 1418.431, 'duration': 5.942}, {'end': 1430.095, 'text': "OK, if we click it, we just want to kind of return out and I'll just console log that it's already speaking.", 'start': 1424.393, 'duration': 5.702}], 'summary': "Developing a function to run when clicking 'speak' or selecting a voice, ensuring it doesn't run when already speaking.", 'duration': 30.85, 'max_score': 1399.245, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81399245.jpg'}, {'end': 1501.45, 'src': 'embed', 'start': 1467.561, 'weight': 6, 'content': [{'end': 1471.706, 'text': "I guess it's not really spelling it's typing already speaking.", 'start': 1467.561, 'duration': 4.145}, {'end': 1475.05, 'text': "And then let's just return.", 'start': 1473.308, 'duration': 1.742}, {'end': 1481.979, 'text': "OK so that will happen if it's actually in the process of speaking and we click the button.", 'start': 1475.07, 'duration': 6.909}, {'end': 1485.198, 'text': 'All right.', 'start': 1484.898, 'duration': 0.3}, {'end': 1494.104, 'text': "So let's let's do a check here to see if the value is not if this actually has something in it.", 'start': 1485.278, 'duration': 8.826}, {'end': 1496.166, 'text': "We want to make sure it's not an empty string.", 'start': 1494.164, 'duration': 2.002}, {'end': 1501.45, 'text': "So let's do an if and we'll take the text input.", 'start': 1496.706, 'duration': 4.744}], 'summary': 'Discussing the process of typing and checking for non-empty input.', 'duration': 33.889, 'max_score': 1467.561, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81467561.jpg'}, {'end': 1552.743, 'src': 'embed', 'start': 1527.897, 'weight': 2, 'content': [{'end': 1533.978, 'text': "Let's say get speak text and I'm going to create a variable called speak text.", 'start': 1527.897, 'duration': 6.081}, {'end': 1540.5, 'text': 'what we want to set this to is new speech.', 'start': 1534.858, 'duration': 5.642}, {'end': 1541.08, 'text': 'where is it?', 'start': 1540.5, 'duration': 0.58}, {'end': 1542.02, 'text': "it's this right here.", 'start': 1541.08, 'duration': 0.94}, {'end': 1544.321, 'text': "so there's a lot of different parts of this API.", 'start': 1542.02, 'duration': 2.301}, {'end': 1552.743, 'text': "we want speech synthesis, synthesis, utterance okay, that's what we want to grab here.", 'start': 1544.321, 'duration': 8.422}], 'summary': "Creating a variable 'speak text' and utilizing the speech synthesis api for utterance.", 'duration': 24.846, 'max_score': 1527.897, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81527897.jpg'}, {'end': 1656.413, 'src': 'embed', 'start': 1618.901, 'weight': 8, 'content': [{'end': 1620.582, 'text': "We don't have to worry about that just yet.", 'start': 1618.901, 'duration': 1.681}, {'end': 1623.806, 'text': "Okay, there's also an event for an error.", 'start': 1621.505, 'duration': 2.301}, {'end': 1633.829, 'text': "so let's say if there's a speak error and we can say speak text dot on, let's see on error.", 'start': 1623.806, 'duration': 10.023}, {'end': 1650.194, 'text': "we'll use an arrow function here and let's just console, we'll do a console dot error and we'll just say something went wrong like that.", 'start': 1633.829, 'duration': 16.365}, {'end': 1654.011, 'text': 'All right, put that on a different line.', 'start': 1652.19, 'duration': 1.821}, {'end': 1656.413, 'text': 'So speak and speak error.', 'start': 1654.431, 'duration': 1.982}], 'summary': 'Setting up event handling for speak and speak error with error message logging.', 'duration': 37.512, 'max_score': 1618.901, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81618901.jpg'}], 'start': 1123.186, 'title': 'Javascript voice selection and speech synthesis', 'summary': 'Covers populating a select list with voices using javascript, creating option elements, and implementing speech synthesis. it emphasizes using a for-each loop, demonstrates creating option elements using document.createelement, and covers various aspects of speech synthesis, including input validation and error handling.', 'chapters': [{'end': 1178.092, 'start': 1123.186, 'title': 'Javascript voice selection', 'summary': 'Explains how to populate a select list with voices using javascript, emphasizing the use of a for-each loop instead of a traditional for loop.', 'duration': 54.906, 'highlights': ['The chapter emphasizes the use of a for-each loop over a traditional for loop for populating the select list with voices using JavaScript.', 'The process involves looping through the voices and creating an option for each one, contributing to a more modern approach to voice selection in JavaScript.']}, {'end': 1368.413, 'start': 1178.112, 'title': 'Creating option elements in javascript', 'summary': 'Demonstrates creating option elements in javascript using document.createelement and manipulating text content and data attributes, resulting in a complete select list of voices from synth.getvoices.', 'duration': 190.301, 'highlights': ['Creating an option element using document.createElement and setting text content to voice name and language in parentheses.', 'Setting data attributes for each option using option.setAttribute to store voice name and language.', 'Appending the created option elements to the select list, resulting in a complete list of voices from synth.getVoices.']}, {'end': 1656.413, 'start': 1370.089, 'title': 'Speech synthesis in javascript', 'summary': 'Covers the process of implementing speech synthesis in javascript, including creating a function to speak, checking for ongoing speech, handling input validation, setting up speech text and its associated events, and error handling during speech synthesis.', 'duration': 286.324, 'highlights': ['A function called speak is created to handle the speech synthesis process, including setting the speech text and defining the on end event.', 'Validation is implemented to check if the system is already speaking when the speak button is clicked.', 'Input validation is performed to ensure that the text input is not empty before proceeding with the speech synthesis process.', 'Error handling is set up to handle any potential errors that may occur during the speech synthesis process.']}], 'duration': 533.227, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81123186.jpg', 'highlights': ['The chapter emphasizes the use of a for-each loop over a traditional for loop for populating the select list with voices using JavaScript.', 'Creating an option element using document.createElement and setting text content to voice name and language in parentheses.', 'A function called speak is created to handle the speech synthesis process, including setting the speech text and defining the on end event.', 'The process involves looping through the voices and creating an option for each one, contributing to a more modern approach to voice selection in JavaScript.', 'Setting data attributes for each option using option.setAttribute to store voice name and language.', 'Validation is implemented to check if the system is already speaking when the speak button is clicked.', 'Input validation is performed to ensure that the text input is not empty before proceeding with the speech synthesis process.', 'Appending the created option elements to the select list, resulting in a complete list of voices from synth.getVoices.', 'Error handling is set up to handle any potential errors that may occur during the speech synthesis process.']}, {'end': 2185.689, 'segs': [{'end': 1756.966, 'src': 'embed', 'start': 1729.518, 'weight': 3, 'content': [{'end': 1738.981, 'text': "So here we're going to take the selected voice and All this is doing is is grabbing the one we select.", 'start': 1729.518, 'duration': 9.463}, {'end': 1743.222, 'text': "It's not actually selecting it from like the API or anything to use.", 'start': 1739.041, 'duration': 4.181}, {'end': 1746.343, 'text': "It's just simply going to grab whichever one we click here.", 'start': 1743.262, 'duration': 3.081}, {'end': 1755.646, 'text': 'So what we need to do is loop through the voices and basically say if the current voice or the current iteration matches what is selected,', 'start': 1746.803, 'duration': 8.843}, {'end': 1756.966, 'text': 'then choose that voice.', 'start': 1755.646, 'duration': 1.32}], 'summary': 'Looping through voices to select a specific one from the available options.', 'duration': 27.448, 'max_score': 1729.518, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81729518.jpg'}, {'end': 1826.137, 'src': 'embed', 'start': 1798.956, 'weight': 2, 'content': [{'end': 1806.441, 'text': "if that's equal, then we simply set the speak text.voice to.", 'start': 1798.956, 'duration': 7.485}, {'end': 1808.941, 'text': 'that voice.', 'start': 1808.28, 'duration': 0.661}, {'end': 1813.165, 'text': "OK Now it'll actually set the voice of speak text.", 'start': 1808.961, 'duration': 4.204}, {'end': 1817.489, 'text': 'You can think of speak text as like the person the person speaking.', 'start': 1813.765, 'duration': 3.724}, {'end': 1823.635, 'text': 'OK And then the last couple of things we need to do is just set the rate and the and the pitch.', 'start': 1818.41, 'duration': 5.225}, {'end': 1826.137, 'text': "So we're going to go outside of that loop there.", 'start': 1823.875, 'duration': 2.262}], 'summary': 'Setting the voice, rate, and pitch for speak text in a programming context.', 'duration': 27.181, 'max_score': 1798.956, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81798956.jpg'}, {'end': 1925.896, 'src': 'embed', 'start': 1895.025, 'weight': 1, 'content': [{'end': 1896.746, 'text': "I'll go ahead and just save that.", 'start': 1895.025, 'duration': 1.721}, {'end': 1902.43, 'text': "And let's set, I'll just say event listeners.", 'start': 1897.867, 'duration': 4.563}, {'end': 1910.044, 'text': 'Okay, so the first event is going to be the actual form submission.', 'start': 1906.761, 'duration': 3.283}, {'end': 1915.688, 'text': 'So when we click this button, we want to basically just call this speak function that we created.', 'start': 1910.084, 'duration': 5.604}, {'end': 1925.896, 'text': 'Okay, which just goes through all this, selects the voice, come down here, select the pitch, the rate, and then actually speaks.', 'start': 1915.708, 'duration': 10.188}], 'summary': 'Setting event listeners for form submission to trigger the speak function.', 'duration': 30.871, 'max_score': 1895.025, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81895025.jpg'}, {'end': 2147.289, 'src': 'heatmap', 'start': 2090.263, 'weight': 0.821, 'content': [{'end': 2095.866, 'text': 'So voice select and we want to add an event listener.', 'start': 2090.263, 'duration': 5.603}, {'end': 2107.171, 'text': "And again we want to listen for a change and we don't need curly braces here either because all we're doing is just calling speak.", 'start': 2096.946, 'duration': 10.225}, {'end': 2115.604, 'text': "OK, so we're just going to call speak again as soon as the voice is changed and save.", 'start': 2110.402, 'duration': 5.202}, {'end': 2119.305, 'text': 'All right, so now we can test everything out.', 'start': 2117.064, 'duration': 2.241}, {'end': 2125.267, 'text': "We haven't done the background animation yet, but that's that's like I said at the end, let's just test this out.", 'start': 2119.345, 'duration': 5.922}, {'end': 2126.208, 'text': "So let's say.", 'start': 2125.327, 'duration': 0.881}, {'end': 2131.99, 'text': 'I hope this app works.', 'start': 2126.228, 'duration': 5.762}, {'end': 2135.051, 'text': 'OK, you ready? I hope this app works.', 'start': 2132.53, 'duration': 2.521}, {'end': 2138.012, 'text': "Yes OK, let's change the rate.", 'start': 2135.751, 'duration': 2.261}, {'end': 2140.143, 'text': 'I hope this app works.', 'start': 2139.562, 'duration': 0.581}, {'end': 2141.103, 'text': 'That works.', 'start': 2140.523, 'duration': 0.58}, {'end': 2147.289, 'text': 'And you can see this is now, as soon as I let go, when I move this, this changes.', 'start': 2141.564, 'duration': 5.725}], 'summary': 'Adding event listener for voice change, testing app functionality.', 'duration': 57.026, 'max_score': 2090.263, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82090263.jpg'}, {'end': 2190.813, 'src': 'embed', 'start': 2158.478, 'weight': 0, 'content': [{'end': 2159.299, 'text': "And let's try it.", 'start': 2158.478, 'duration': 0.821}, {'end': 2160.7, 'text': 'I hope this app works.', 'start': 2159.739, 'duration': 0.961}, {'end': 2164.703, 'text': "Okay, let's try a different voice.", 'start': 2160.72, 'duration': 3.983}, {'end': 2166.485, 'text': "We'll choose Kermit.", 'start': 2164.723, 'duration': 1.762}, {'end': 2167.986, 'text': 'I hope this app works.', 'start': 2166.965, 'duration': 1.021}, {'end': 2175.419, 'text': "Now notice, as soon as I select a voice, it plays, it speaks, and that's because of this last event here.", 'start': 2168.453, 'duration': 6.966}, {'end': 2183.187, 'text': 'Because it fires off a change event, and then it calls the speak function, which we created above.', 'start': 2177.702, 'duration': 5.485}, {'end': 2185.689, 'text': 'All right, so everything seems to be working.', 'start': 2183.207, 'duration': 2.482}, {'end': 2190.813, 'text': 'Now we just need to add the bonus functionality of the background image.', 'start': 2185.749, 'duration': 5.064}], 'summary': 'Testing app with different voices successful, added bonus background image functionality', 'duration': 32.335, 'max_score': 2158.478, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82158478.jpg'}], 'start': 1657.473, 'title': 'Javascript text-to-speech app', 'summary': 'Covers working with voices in javascript, setting voice, pitch, and rate for a text-to-speech app, adding event listeners, resulting in successful functionality and testing.', 'chapters': [{'end': 1798.956, 'start': 1657.473, 'title': 'Working with voices in javascript', 'summary': 'Explains how to work with voices in javascript, including setting the selected voice, looping through available voices, and matching the selected voice name to choose the voice. it also covers accessing and setting attributes of the voices.', 'duration': 141.483, 'highlights': ['The chapter explains how to work with voices in JavaScript, including setting the selected voice, looping through available voices, and matching the selected voice name to choose the voice.', 'It also covers accessing and setting attributes of the voices.', 'The script involves creating a variable called Selected voice and setting it to the selected options from a select object, then retrieving and setting the data name attribute.', 'The process involves looping through the available voices and implementing a simple if statement to match the selected voice name for choosing the voice.']}, {'end': 2185.689, 'start': 1798.956, 'title': 'Javascript text-to-speech app', 'summary': 'Discusses setting voice, pitch, and rate for a javascript text-to-speech app and adding event listeners for form submission, rate value change, and voice selection, resulting in successful functionality and testing.', 'duration': 386.733, 'highlights': ['Setting voice, pitch, and rate The chapter explains how to set the voice, pitch, and rate for a JavaScript text-to-speech app, allowing for customization of speech parameters based on user input.', 'Adding event listeners for form submission, rate value change, and voice selection The chapter demonstrates the addition of event listeners for form submission, rate value change, and voice selection, enabling the app to respond dynamically to user interactions.', 'Successful functionality and testing The chapter concludes with successful testing of the JavaScript text-to-speech app, ensuring that voice, pitch, and rate adjustments, as well as voice selection, function as intended.']}], 'duration': 528.216, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G81657473.jpg', 'highlights': ['The chapter concludes with successful testing of the JavaScript text-to-speech app, ensuring that voice, pitch, and rate adjustments, as well as voice selection, function as intended.', 'Adding event listeners for form submission, rate value change, and voice selection enables the app to respond dynamically to user interactions.', 'The chapter explains how to set the voice, pitch, and rate for a JavaScript text-to-speech app, allowing for customization of speech parameters based on user input.', 'The chapter explains how to work with voices in JavaScript, including setting the selected voice, looping through available voices, and matching the selected voice name to choose the voice.']}, {'end': 2647.738, 'segs': [{'end': 2272.928, 'src': 'embed', 'start': 2239.936, 'weight': 0, 'content': [{'end': 2241.858, 'text': "There's nothing else we have to do here I believe.", 'start': 2239.936, 'duration': 1.922}, {'end': 2243.399, 'text': "So let's go in our JavaScript.", 'start': 2241.898, 'duration': 1.501}, {'end': 2255.024, 'text': "OK, Now when, as soon as the the speak function fires off, that's when we want to show the the image right.", 'start': 2244.24, 'duration': 10.784}, {'end': 2268.383, 'text': "so let's go to our speak function and we're going to go right to the top of it and let's say add background animation.", 'start': 2255.024, 'duration': 13.359}, {'end': 2270.445, 'text': "i guess we'll call it okay.", 'start': 2268.383, 'duration': 2.062}, {'end': 2272.928, 'text': 'so we can do this by selecting the body.', 'start': 2270.445, 'duration': 2.483}], 'summary': 'In the javascript code, the image should be shown when the speak function fires off.', 'duration': 32.992, 'max_score': 2239.936, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82239936.jpg'}, {'end': 2361.057, 'src': 'embed', 'start': 2337.256, 'weight': 1, 'content': [{'end': 2344.422, 'text': "Now, I don't know if I mentioned this yet, but if you're not running this on a server, like you're not in a root directory of a server,", 'start': 2337.256, 'duration': 7.166}, {'end': 2347.985, 'text': 'the paths might get might not get found.', 'start': 2344.422, 'duration': 3.563}, {'end': 2355.752, 'text': 'Like if you just open index HTML on your desktop, it might not work because it might not find this image just to let you know.', 'start': 2348.346, 'duration': 7.406}, {'end': 2358.114, 'text': "But, you know, it's not a big deal.", 'start': 2356.753, 'duration': 1.361}, {'end': 2361.057, 'text': 'If you were to deploy it to a host, then it would work.', 'start': 2358.154, 'duration': 2.903}], 'summary': 'Paths may not be found if not running on a server, but deploying to a host will resolve the issue.', 'duration': 23.801, 'max_score': 2337.256, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82337256.jpg'}, {'end': 2557.085, 'src': 'embed', 'start': 2525.249, 'weight': 2, 'content': [{'end': 2526.39, 'text': 'So we have to take care of that.', 'start': 2525.249, 'duration': 1.141}, {'end': 2529.852, 'text': "And the way that we're going to do it is going down to the on end.", 'start': 2526.47, 'duration': 3.382}, {'end': 2533.034, 'text': "Remember, this fires off as soon as it's done speaking.", 'start': 2530.272, 'duration': 2.762}, {'end': 2538.517, 'text': "If I open my console, it says done speaking after it's done speaking.", 'start': 2533.094, 'duration': 5.423}, {'end': 2547.623, 'text': "So let's then take the body and let's say body.style.background.", 'start': 2538.637, 'duration': 8.986}, {'end': 2551.679, 'text': "And let's set it back to just the color.", 'start': 2549.196, 'duration': 2.483}, {'end': 2553.06, 'text': 'OK, no image.', 'start': 2551.699, 'duration': 1.361}, {'end': 2557.085, 'text': "All right, so let's go back and try it out.", 'start': 2554.302, 'duration': 2.783}], 'summary': 'Implementing a background color change function with console confirmation.', 'duration': 31.836, 'max_score': 2525.249, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82525249.jpg'}, {'end': 2630.987, 'src': 'embed', 'start': 2594.874, 'weight': 4, 'content': [{'end': 2595.815, 'text': "Let's hope it works.", 'start': 2594.874, 'duration': 0.941}, {'end': 2598.088, 'text': "That's good.", 'start': 2597.608, 'duration': 0.48}, {'end': 2602.751, 'text': "Another thing that's pretty cool is that it recognizes punctuation.", 'start': 2598.469, 'duration': 4.282}, {'end': 2605.513, 'text': 'It recognizes punctuation, at least commas.', 'start': 2602.891, 'duration': 2.622}, {'end': 2617.1, 'text': "Like if I do, let's say, how are you? I am good.", 'start': 2605.553, 'duration': 11.547}, {'end': 2618.421, 'text': 'Okay, without a comma.', 'start': 2617.12, 'duration': 1.301}, {'end': 2620.062, 'text': 'How are you? I am good.', 'start': 2618.841, 'duration': 1.221}, {'end': 2625.384, 'text': 'But if I put a comma in there, How are you? I am good.', 'start': 2620.722, 'duration': 4.662}, {'end': 2626.625, 'text': 'It does a little pause.', 'start': 2625.504, 'duration': 1.121}, {'end': 2628.366, 'text': "So I think that's pretty cool.", 'start': 2627.185, 'duration': 1.181}, {'end': 2630.987, 'text': "I don't think the question mark works.", 'start': 2629.286, 'duration': 1.701}], 'summary': 'Speech recognition recognizes punctuation, like commas, but not question marks.', 'duration': 36.113, 'max_score': 2594.874, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82594874.jpg'}], 'start': 2185.749, 'title': 'Adding background image functionality and troubleshooting speech recognition', 'summary': 'Details adding a background image to the website, modifying body color, integrating the image in javascript speak function, and troubleshooting issues with image display, speech recognition, and refining the code to handle empty input and punctuation.', 'chapters': [{'end': 2421.768, 'start': 2185.749, 'title': 'Adding background image functionality', 'summary': 'Details adding a background image to the website, modifying the body color and integrating the image in the javascript speak function, cautioning about potential path issues when running the code on a local file system.', 'duration': 236.019, 'highlights': ['The chapter details adding a background image to the website The speaker explains the process of adding a background image to the website by modifying the body color and integrating the image in the JavaScript speak function.', 'Cautioning about potential path issues when running the code on a local file system The speaker warns about potential path issues when running the code on a local file system, stating that the image might not be found if the code is not run on a server or in the root directory.']}, {'end': 2647.738, 'start': 2422.935, 'title': 'Troubleshooting and refining speech recognition', 'summary': 'Discusses troubleshooting issues with image display and speech recognition, refining the code to handle empty input, and adjusting background styling based on speech input, while also highlighting the recognition of punctuation in speech.', 'duration': 224.803, 'highlights': ['The chapter discusses troubleshooting the issue of image display and refining the code to handle empty input, with emphasis on adjusting background styling based on speech input.', 'The speech recognition system is refined to handle empty input and adjust background styling based on speech input.', 'Recognition of punctuation in speech is highlighted, with specific focus on commas and periods.']}], 'duration': 461.989, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZORXxxP49G8/pics/ZORXxxP49G82185749.jpg', 'highlights': ['The chapter details adding a background image to the website by modifying the body color and integrating the image in the JavaScript speak function.', 'The speaker warns about potential path issues when running the code on a local file system, stating that the image might not be found if the code is not run on a server or in the root directory.', 'The chapter discusses troubleshooting the issue of image display and refining the code to handle empty input, with emphasis on adjusting background styling based on speech input.', 'The speech recognition system is refined to handle empty input and adjust background styling based on speech input.', 'Recognition of punctuation in speech is highlighted, with specific focus on commas and periods.']}], 'highlights': ['The application allows users to customize speech rate, pitch, and voice, supporting various languages and accents.', 'The web speech API is compatible with Chrome, Edge, Firefox, and Safari, ensuring a seamless experience across different browsers.', 'The chapter concludes with successful testing of the JavaScript text-to-speech app, ensuring that voice, pitch, and rate adjustments, as well as voice selection, function as intended.', 'Adding event listeners for form submission, rate value change, and voice selection enables the app to respond dynamically to user interactions.', 'The chapter explains how to set the voice, pitch, and rate for a JavaScript text-to-speech app, allowing for customization of speech parameters based on user input.']}