speechSynthesis.speak not working in chrome - google-chrome

I'm using chrome Version 55.0.2883.87 m (64-bit) on Windows 10.
The following simple html file reproduces the problem and is extracted from my more complex app. It is supposed to speak the 3 words on page load. It works on MS Edge and Firefox but does not work on chrome. This code was working for me on Chrome no problem a couple weeks back.
<html>
<head>
<script lang="javascript">
window.speechSynthesis.speak(new SpeechSynthesisUtterance("cat"));
window.speechSynthesis.speak(new SpeechSynthesisUtterance("dog"));
window.speechSynthesis.speak(new SpeechSynthesisUtterance("bark"));
</script>
</head>
<body></body>
</html>

I may never know for sure, because this problem was intermittent, but it seemed to go away after I started to cancel right before speak.
utter = new window.SpeechSynthesisUtterance("cat");
window.speechSynthesis.cancel();
window.speechSynthesis.speak(utter);
I don't think the cancel necessarily has to come between the utterance object creation and use. Just that it come before every speak. I may have had a different problem as I was only creating one utterance object, not a bunch. I did only see it on Chrome 78. Using Windows 7, 64-bit. Never saw the problem on Firefox or Edge.
EDIT 2 weeks later. No recurrences after several dozen tries. It seems .cancel() solved my problem. My symptoms were: calling speechSynthesis.speak() in Chrome would sometimes not start the speech. There were no immediate indications of a problem in the code, speechSynthesis.speaking would be true and .pending would be false. There would be no events from the utterance object. Normally, when speech would work, I'd get a 'start' event about 0.1 seconds after calling .speak().

speechSynthesis.speak() is no longer allowed without user activation in Google's Chrome web browser since 2018. It violates autoplay policy of Google Chrome. Thus Google Chrome has managed to revoke it's autoplay functionality but you can make use of it by adding a button to make a custom call.
You can visit here to check the status provided by chrome itself also below is the image attached which clearly shows that speechSynthesis.speak() call is prohibited without user's permission.
Link to image
Link to article by Google Chrome

To add to this, the issue for me was the playback rate on the instance of SpeechSynthesisUtterance was above 2. I discovered it must be set to 2 or less in chrome (although it works with higher rates in other browsers like safari).
In chrome, if the utterance rate is above 2, it causes the window.speechSynthesis to be stuck, and needs window.speechSynthesis.cancel() before it will play audio again (at a valid rate below 2) via .speak().

Did your text to voice tryout work only once? Here is why.
In chrome you have to cancel the speechSynthesis, otherwise its not compliant to googles autoplay policy. So you should start your script with:
window.speechSynthesis.cancel()
To cancel any speech synthesis that happened before.

resultsDisplay = document.getElementById("rd");
startButton = document.getElementById("startbtn");
stopButton = document.getElementById("stopbtn");
recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.msSpeechRecognition)();
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 5;
recognition.onresult = function(event) {
resultsDisplay.innerHTML = "You Said:" + event.results[0][0].transcript;
};
function start() {
recognition.start();
startButton.style.display = "none";
stopButton.style.display = "block";
}
function stop() {
recognition.stop();
startButton.style.display = "block";
stopButton.style.display = "none";
}
.resultsDisplay {width: 100%; height: 90%;}
#stopbtn {display: none;}
<div class="resultsDisplay" id="rd"></div>
<br/>
<center>
<button onclick="start()" id="startbtn">Start</button>
<button onclick="stop()" id="stopbtn">Stop</button>
</center>
Try
utterance = new SpeechSynthesisUtterance("cat, dog, bark");
speechSynthesis.speak(utterance);
I made a Weave at LiveWeave.

Instead of specifying the text while calling new, you could try specifying an object with rate, volume, and text separately, and then converting it to voice.

Related

HTML5 drag-drop between different browsers and apps

Browser quirks aside, HTML5 drag and drop works between different windows of the same browser. When I run up the web app in different browsers, I still get the dragover events but the data is missing.
Here are the the dragStart and dragOver handlers. Not very interesting, they just implement what MDN tells you to do. The code is Typescript.
public dragStart(e: DragEvent): boolean {
e.dataTransfer.setData("text/json", JSON.stringify(this.Model));
return true;
}
public dragOver(e: DragEvent): boolean {
if (e.dataTransfer.items.length) {
let raw = e.dataTransfer.items[0];
if (raw && raw.type === "text/json") {
//highlight drop target
}
return false;
}
return true;
}
This code running in two Chrome windows, it works - I can drag between the windows. This code running in two Firefox windows, it works.
Chrome to Firefox, or Firefox to Chrome, I get events but no data.
Why and what can I do about this? And if it cannot be made to work, what's the point of firing drag events for drag from another app if you (Google, Mozilla etc) aren't going to surface the data?
This probably isn't the end of the world for copying from one browser app to another; a given user will more than likely use the same browser for both. But I had visions of interop with desktop applications, and this does not bode well.
When I change the "mime type" used with setData and getData from text/json (which is what the data is) to text/plain, suddenly it works between Firefox and Chrome, and I can also drag a node to a text editor, where unsurprisingly the JSON is inserted as text.
And it works with Edge now. Crikey, according to mdn you can make up your own values. They left out "but not if you want interop with another app"
I had thought to use the type to decide whether to allow drop, and text/plain does little to help me wit that. I can try a parse and if that succeeds I can check some attributes, but this is rather heavyweight, and according to Drag'n'drop dataTransfer.getData empty it won't work anyhow.

Safari 6.0.2 not calling onaudioprocess

I've earlier successfully used the JavaScriptAudioNode in the Web Audio API to synthesize and mix audio both in Chrome and Safari 6.0. However, the latest version of Safari no longer appears to work, because it does not call onaudioprocess to fill the source buffers.
This is a simplified example which plays only silence and appends text to the document body on each call to onaudioprocess:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
var context = new webkitAudioContext();
var mixerNode=context.createJavaScriptNode(2048, 0, 2);
mixerNode.onaudioprocess=function(ape) {
var buffer=ape.outputBuffer;
for(var s=0;s<buffer.length;s++)
{
buffer.getChannelData(0)[s]=0;
buffer.getChannelData(1)[s]=0;
}
$("body").append("buffering<br/>");
};
$("body").html("");
mixerNode.connect(context.destination);
return false;
});
});
</script>
</head>
<body>
start
</body>
</html>
The above example works in Chrome as expected, but not in desktop Safari. The iOS version of Safari does not work either, but it never did work for me in the first place.
Calling context.createJavaScriptNode does return a proper object of type JavaScriptAudioNode and connecting it to the destination node does not throw any exceptions. context.activeSourceCount remains at zero, but this is also the case in Chrome as it apparently only counts active nodes of type AudioBufferSourceNode. context.currentTime also increments as expected.
Am I doing something wrong here or is this an actual bug or a missing feature in Safari? The Apple documentation has no mention of JavaScriptAudioNode (nor the new name, ScriptProcessorNode) but it did work before on the first release of Safari 6. The iOS Safari requirement for user input doesn't seem to help, as the example above should take care of that.
The simple example can be found here and a more complex one is my Protracker module player which exhibits the same behaviour.
There are a couple bugs in Safari's implementation of the Web Audio API that you'll need to look out for. The first is in the createJavaScriptNode constructor... it seems to have problems with the "input channels" param being set to 0. Try changing it to this:
createJavaScriptNode(2048, 1, 2)
The second issue has to do with garbage collection (I think); once your mixerNode variable is out of scope, Safari seems to stop firing the onaudioprocess callback. One solution is to introduce mixerNode at the top-level scope (i.e. declaring var mixerNode; at the top of your script) and then store your JavaScriptNode in that top-level variable. If you plan on dynamically creating multiple mixerNodes, you can achieve the same effect by storing references to them in a top-level array variable.
If you make these two changes (input channel param set to 1, maintaining a reference to the mixerNode) then your script should work in Safari as expected.

How to solve webkitRequestAnimationFrame giving extremely high FPS

Today I've been trying to get myself acquainted with anything new HTML5 has to offer, in particular the canvas. I came upon the site www.html5canvastutorials.com and began following some of the tutorials and playing around with the code a bit in different browsers. When I got to the following example I noticed something odd in google chrome. http://www.html5canvastutorials.com/advanced/html5-canvas-oscillation-animation/
The webkitRequestAnimationFrame function is supposed to help reduce FPS (and thus CPU costs) when not actively on the site, for example when you go to a different tab. However, when I tried the example, I noticed that this does not always appear to give pleasant results.
Google Chrome as active window, site on current tab: Get around 60
FPS, great!
Google Chrome as active window, on a different tab: Get
around 1 FPS, very good.
Google Chrome as active window, on my TV
(used as second monitor), 120 FPS, odd, but no complaints.
Google Chrome not as active window, but on a different tab, also around 1
FPS or so, perfect.
Then the bad part:
If my site is on the current tab, but I have another window completely covering the google chrome window (say a maximized window for example), the FPS shoots up to around 2500 (and consequently maxes one CPU core).
Everything works perfectly normal when I try the same site in Firefox.
This fiddle's an example where it shows the average FPS since the last refresh: http://jsfiddle.net/kmKZa/55/
(I pretty much copied the code from the tutorial site)
I would like to know how I can prevent these scary CPU spikes if anybody has any ideas. Thanks in advance for any advice!
One possible solution is to simply cancel the AnimationFrame loop when you blur the window, and request it again when you refocus it.
var isPaused = false,
animFrame;
loop();
$(window)
.on('focus', function() {
if( isPaused ) {
isPaused = false;
loop();
}
})
.on('blur', function() {
cancelRequestAnimationFrame( animFrame );
isPaused = true;
});
function loop() {
//your crazy loop code
animFrame = requestAnimationFrame( loop );
}
RAF automatically stop execution on "idle".
U don't need to stop RAF loop execution

HTML5 geolocation not working

I'm trying to learn how to use HTML5 geolocation and am having trouble getting the following script to run properly:
<script src="js/jquery-1.4.2.min.js"></script>
<script>
jQuery(window).ready(function(){
jQuery("#btnInit").click(initiate_geolocation);
});
function initiate_geolocation() {
navigator.geolocation.getCurrentPosition(handle_geolocation_query);
}
function handle_geolocation_query(position){
alert('Lat: ' + position.coords.latitude + ' ' +
'Lon: ' + position.coords.longitude);
}
</script>
My HTML contains a button that references the #btnInit jQuery function; however, the script does not display any alert popup boxes. Moreover, it seems that the script is pausing prior to the line: jQuery(window).ready(function(){
What are my next steps for getting HTML5 geolocation working?
Your code works perfectly for me, see this fiddle. Is your browser supporting geolocation?
Depending on your browser, you should see somewhere a notice to allow the browser to get your location. You must allow this, to get your code working.
html 5 geoloaction is working on ie9 but not in Mozilla higher version and IE lower version so better use location by ip
I've had the same issues, my solution was to run geolocation from a wifi point of reference rather than ethernet. All I can suggest is my modem is firewalling any requests back about me and my location through my private network, but then locates my position through my mac address and SSID reference. See the article: How, exactly does HTML5's GeoLocation work?

Preloading images (in Chrome) [duplicate]

I am pre-loading some images and then using them in a lightbox. The problem I have is that although the images are loading, they aren't being displayed by the browser.
This issue is specific to Chrome. It has persisted through Chrome 8 - 10, and I've been trying on and off to fix it all this time and have got nowhere.
I have read these similar questions,
Chrome not displaying images though assets are being delivered to browser
2 Minor Crossbrowser CSS Issues. Background images not displaying in Google Chrome?
JavaScript preloaded images are getting reloaded
Which all detail similar behaviour but in Chrome for Mac. Whereas this is happening in Windows.
All other browsers seem to be fine.
If you have Firefox and Chrome open, load the page in Firefox, and then in Chrome, the images appear.
Once you have manually loaded the images, using the Webkit webdev toolbar thingy, they always show up
All the links the images and such are fine and working
Clearing everything from Chrome doesn't seem to make any difference (cache, history, etc)
If anyone has any ideas it would be fantastically helpfull, as I'm literally all out of options here.
PS, Apologies if there are late replies, I'm off on holiday for a week tomorrow! :D
Update
Here is the javascript function which is preloading the images.
var preloaded = new Array();
function preload_images() {
for (var i = 0; i < arguments.length; i++){
document.write('<');
document.write('img src=\"'+arguments[i]+'\" style=\"display:none;\">');
};
};
Update
I'm still having issues with this, and I've removed the whole preloading images function. Perhaps delivering a style sheet via document.write() isn't the best way?
Chrome might not be preloading them as it's writing to the DOM with no display, so it might be intelligent enough to realise it doesn't need to be rendered. Try this instead:
var preloaded = new Array();
function preload_images(){
for (var x = 0; x < preload_images.arguments.length; x++)
{
preloaded[x] = new Image();
preloaded[x].src = preload_images.arguments[x];
}
}
The Javascript Image object has a lot of useful functions as well you might find useful:
http://www.javascriptkit.com/jsref/image.shtml
onabort()
Code is executed when user aborts the
downloading of the image.
onerror()
Code is executed when an error occurs
with the loading of the image (ie: not
found). Example(s)
onload()
Code is executed when the image
successfully and completely downloads.
And then you also have the complete property which true/false tells you if the image has fully (pre)loaded.
It turns out that Chrome takes into account the HTTP Caching and discards any preloaded images immediately after preload if the Caching is incorrectly set to expire.
In my case I am generating the images dynamically and by default the response was sent to the browser with immediate expiration.
To fix it I had to set the following below:
Response.Cache.SetExpires(DateTime.Now.AddYears(1));
Response.Cache.SetCacheability(HttpCacheability.Public);
return File(jpegStream, "image/jpeg");