Skip to content

Instantly share code, notes, and snippets.

@wesbos wesbos/lol.js
Last active Feb 19, 2019

Embed
What would you like to do?
// paste in your console
speechSynthesis.onvoiceschanged = function() {
var msg = new SpeechSynthesisUtterance();
msg.voice = this.getVoices().filter(v => v.name == 'Cellos')[0];
msg.text = Object.keys(window).join(' ');
this.speak(msg);
};
@wesbos

This comment has been minimized.

Copy link
Owner Author

commented Feb 16, 2016

For an extra treat, change Cellos to Hysterical

sorry.

@therealklanni

This comment has been minimized.

Copy link

commented Feb 16, 2016

Love it!

@jabranr

This comment has been minimized.

Copy link

commented Feb 16, 2016

LOL awesome!

@therealklanni

This comment has been minimized.

Copy link

commented Feb 16, 2016

Bad News is pretty great, too.

@nuel

This comment has been minimized.

Copy link

commented Feb 17, 2016

this is amazing

@TomOffringa

This comment has been minimized.

Copy link

commented Feb 17, 2016

:D

@wimleers

This comment has been minimized.

Copy link

commented Feb 17, 2016

AWESOME! :D

@elijahmanor

This comment has been minimized.

Copy link

commented Feb 17, 2016

Nice one Wes! Made some minor tweaks to find unique globals by comparing current globals to an iframe's globals.

( function() {
  "use strict";
  const getGlobals = callback => {
    var iframe = document.createElement( "iframe" );
    iframe.addEventListener( "load", () => {
      const windowKeys = Object.keys( window );
      const iframeKeys = Object.keys( iframe.contentWindow );
      const uniqueKeys = windowKeys.reduce( ( memo, key ) => {
        if ( !~iframeKeys.indexOf( key ) ) {
          memo.push( key );
        }
        return memo;
      }, [] );
      callback ( uniqueKeys );
    } );
    iframe.src = "about:blank";
    document.body.appendChild( iframe );
  }
  const msg = new SpeechSynthesisUtterance();
  msg.voice = speechSynthesis.getVoices().filter( v => v.name == "Cellos" )[ 0 ];
  getGlobals( keys => {
    console.log( keys );
    msg.text = keys.join( " " );
    speechSynthesis.speak( msg );
  } );
} () );
@betacar

This comment has been minimized.

Copy link

commented Feb 17, 2016

In case you're wondering, use speechSynthesis.cancel() to shut it up.

@groteworld

This comment has been minimized.

Copy link

commented Feb 17, 2016

Took @elijahmanor's code and added a iframe.remove() after callback is made, to cleanup resulting iframes. I threw this into a bookmarklet maker. Baby, you got yourself a stew going!

"use strict";

(function () {
(function () {
  "use strict";
  var getGlobals = function getGlobals(callback) {
    var iframe = document.createElement("iframe");
    iframe.addEventListener("load", function () {
      var windowKeys = Object.keys(window);
      var iframeKeys = Object.keys(iframe.contentWindow);
      var uniqueKeys = windowKeys.reduce(function (memo, key) {
        if (! ~iframeKeys.indexOf(key)) {
          memo.push(key);
        }
        return memo;
      }, []);
      callback(uniqueKeys);
      iframe.remove();
    });
    iframe.src = "about:blank";
    document.body.appendChild(iframe);
  };
  var msg = new SpeechSynthesisUtterance();
  msg.voice = speechSynthesis.getVoices().filter(function (v) {
    return v.name == "Cellos";
  })[0];
  getGlobals(function (keys) {
    console.log(keys);
    msg.text = keys.join(" ");
    speechSynthesis.speak(msg);
  });
})();
@wesbos

This comment has been minimized.

Copy link
Owner Author

commented Feb 17, 2016

Ahahah this is amazing. Only a bunch of developers would take a joke and build it out even more 😭

@akhelloufi

This comment has been minimized.

Copy link

commented Feb 17, 2016

console.log(window.speechSynthesis.getVoices());
in google chrome give all the name voice with many languages

@elijahmanor

This comment has been minimized.

Copy link

commented Feb 17, 2016

@groteworld nice addition to remove the iframe & a bookmarklet is a good idea.
@wesbos it's hard to not be a geek ;)

@mrspeaker

This comment has been minimized.

Copy link

commented Feb 17, 2016

Damn you! Just redundified my js1k entry!

@jnewc

This comment has been minimized.

Copy link

commented Feb 17, 2016

"Good News" 👍

@chrislaughlin

This comment has been minimized.

Copy link

commented Feb 18, 2016

👍

@LPGhatguy

This comment has been minimized.

Copy link

commented Feb 18, 2016

I was able to get all the voices to work on OS X with Chrome 49, but on Windows with Chrome 50 I'm not getting any of the named voices, just the boring Google ones. 😦

@L1fescape

This comment has been minimized.

Copy link

commented Feb 18, 2016

Awesome! You can also invoke speech synthesis from outside the onvoiceschanged method:

var msg = new SpeechSynthesisUtterance();
msg.voice = speechSynthesis.getVoices().filter(v => v.name == 'Alex')[0];
msg.text = 'hi there from the dev tools console';
speechSynthesis.speak(msg);
@StoneCypher

This comment has been minimized.

Copy link

commented Feb 18, 2016

In case you'd like to know what they all sound like (there's a bunch of funny ones)

var msgs    = speechSynthesis.getVoices().map( (v, i) => { return { voice: v, text: `hi there from the voice named ${v.name}` }; }),
    speaker = new SpeechSynthesisUtterance(),
    halt    = false;

function speakOne(i) {
  if (halt) { halt = false; return; }
  speaker.voice = msgs[i].voice;
  speaker.text  = msgs[i].text;
  speechSynthesis.speak(speaker);
  console.log(`Saying "${speaker.voice.name}"`);
}

function speakAll() {
  var cursor = 0;
  speaker.onend = () => (++cursor) >= msgs.length? true : speakOne(cursor);  // chain each end
  speakOne(cursor);                                                          // start the series
}

To bail, set halt to true in the console. speechSynthesis.cancel() will only cancel the currently speaking voice.

I like Bad News, Bells, Cellos, Hysterical, and the way the language-specific Google voices butcher the words "hi there from."

Call speakOne(i) to listen to any specific voice by index, or speakAll() to listen to them all.

I also gisted this here.

@msikma

This comment has been minimized.

Copy link

commented Feb 18, 2016

I've got Japanese too. Is this standard in all Chrome installs?

var msg = new SpeechSynthesisUtterance();
msg.voice = speechSynthesis.getVoices().filter(v => v.name == 'Google 日本語')[0];
msg.text = 'こんにちは皆さん!';
speechSynthesis.speak(msg);
@ToreJuloe

This comment has been minimized.

Copy link

commented Feb 18, 2016

@akenn The reason it's wrapped in the voiceschanged eventlistener, is that the voices are loaded asynchronously and this way you can make sure that they actually exist before you start using them.

It's no problem when you just run the snippet in the dev console, but if it's embedded on a page and set to run immediately, you'll get an error.

Here's a pretty cool Pen to play around with the different voices.

@L1fescape

This comment has been minimized.

Copy link

commented Feb 18, 2016

@ToreJuloe oh good to know - thanks!

@mathiasbynens

This comment has been minimized.

Copy link

commented Feb 18, 2016

Why not use Array#find? .filter(v => v.name == 'Cellos')[0].find(v => v.name == 'Cellos')

@msikma Not in my Opera/Chrome.

@riston

This comment has been minimized.

Copy link

commented Feb 19, 2016

Its not working in Linux window.speechSynthesis.getVoices() returns empty array no "voices" :(

@incleaf

This comment has been minimized.

Copy link

commented Mar 14, 2016

Wow 👍

@imtaehyun

This comment has been minimized.

Copy link

commented Mar 15, 2016

Love it!

@pokono

This comment has been minimized.

Copy link

commented Mar 24, 2016

Awesome!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.