Skip to content

Instantly share code, notes, and snippets.

@rlemon
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rlemon/251237559c347561f0d7 to your computer and use it in GitHub Desktop.
Save rlemon/251237559c347561f0d7 to your computer and use it in GitHub Desktop.
spoken chat
// ==UserScript==
// @name Spoken Chat
// @author Robert Lemon
// @version 0.42
// @namespace
// @description Speaks the chat.
// @include http://chat.stackoverflow.com/rooms/*
// ==/UserScript==
function exec(fn) {
var script = document.createElement('script');
script.setAttribute('type', 'application/javascript');
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
}
exec(function() {
var reading = true;
var toggle = document.createElement('input');
toggle.checked = true;
toggle.type = 'checkbox';
toggle.onchange = function(e) {
console.log(this.checked);
reading = this.checked;
};
document.getElementById('chat-buttons').appendChild(toggle);
var speechUtteranceChunker = function(utt, settings, callback) {
settings = settings || {};
var chunkLength = settings && settings.chunkLength || 160;
var pattRegex = new RegExp('^.{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[\.\!\?\,]{1}|^.{1,' + chunkLength + '}$|^.{1,' + chunkLength + '} ');
var txt = (settings && settings.offset !== undefined ? utt.text.substring(settings.offset) : utt.text);
var chunkArr = txt.match(pattRegex);
if (chunkArr[0] !== undefined && chunkArr[0].length > 2) {
var chunk = chunkArr[0];
var newUtt = new SpeechSynthesisUtterance(chunk);
for (x in utt) {
if (utt.hasOwnProperty(x) && x !== 'text') {
newUtt[x] = utt[x];
}
}
newUtt.onend = function() {
settings.offset = settings.offset || 0;
settings.offset += chunk.length - 1;
speechUtteranceChunker(utt, settings, callback);
}
console.log(newUtt); //IMPORTANT!! Do not remove: Logging the object out fixes some onend firing issues.
//placing the speak invocation inside a callback fixes ordering and onend issues.
if (reading) {
setTimeout(function() {
speechSynthesis.speak(newUtt);
}, 0);
}
}
};
new MutationObserver(function(records) {
records.forEach(function(record) {
[].forEach.call(record.addedNodes, function(node) {
if (node.classList && node.classList.contains('message') && !node.classList.contains('pending')) {
var anchor = node.parentNode.parentNode.firstChild,
user = anchor.querySelector('.username').textContent,
utterance = new SpeechSynthesisUtterance(user + ' said: ' + node.textContent),
voices = speechSynthesis.getVoices();
utterance.voice = voices[2];
speechUtteranceChunker(utterance, {
chunkLength: 120
});
}
});
});
}).observe(document.getElementById('chat'), {
childList: true,
subtree: true
});
});
@Tyler-H
Copy link

Tyler-H commented Jun 11, 2015

Very cool!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment