您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
ChatGPT
- // ==UserScript==
- // @name Change ChatGPT Image And Text To Speech Function
- // @namespace Change ChatGPT Image And Text To Speach Function
- // @version 0.2
- // @description ChatGPT
- // @author kaes-u-paya for text to speech and mei for the image change
- // @match https://chat.openai.com/chat
- // @grant none
- // @license MIT
- // ==/UserScript==
- //var link = "https://s3.bmp.ovh/imgs/2022/12/18/f2294e4eb27e9161.jpg";
- var link = "https://cdn4.iconfinder.com/data/icons/artificial-intelligence-35/64/artificial-intelligence-ai-avatar-robot-512.png";
- var circle = false;
- var shadow = false;
- var VoiceSettingsTags = `
- <div class="properties">
- <label for="voice">Voice:</label>
- <select id="voice"></select>
- <div></div>
- <label for="pitch">Pitch:</label>
- <input id="pitch" type="range" min="0.1" max="2" step="0.1" value="1">
- <output for="pitch">1</output>
- <label for="rate">Rate:</label>
- <input id="rate" type="range" min="0.1" max="2" step="0.1" value="1">
- <output for="rate">1</output>
- <label for="volume">Volume:</label>
- <input id="volume" type="range" min="0" max="1" step="0.1" value="1">
- <output for="volume">1</output>
- </div>`;
- document.head.appendChild(Object.assign(document.createElement("style"), {textContent: `
- .properties {
- position:absolute;
- z-index:10000;
- width: 430px;
- top:5px;
- right:5px;
- display: grid;
- grid-template-columns: max-content minmax(0, auto) 40px;
- gap: 10px;
- padding: 10px;
- background-color: #0003;
- }
- #voice {
- padding-top:0px;
- height: 30px;
- font-size: 14px;
- background: rgba(0, 0, 0, 0.5);
- color: #fff;
- text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
- }
- `
- }));
- let VoiceSettings = document.createElement('div');
- VoiceSettings.innerHTML = VoiceSettingsTags;
- document.body.appendChild(VoiceSettings);
- //var textinput = "Hi how are you?";
- document.addEventListener("DOMNodeInserted", function(event) {
- /*
- * alert('inserted ' + event.target.childNodes[0].childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('img')[1].alt);// new node -- extract your name from google account avatar logo alt text
- */
- /*
- try {
- let AiLogo = event.target.childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('svg')[0].getAttribute("class"); // find the event when the AI logo will be inserted - class -> 'h-6 w-6'
- } catch (event) {
- if (event.name === 'TypeError') { //element doesnt exist yet (undefined) - wait for the element to be created
- } else {
- throw event; // re-throw the error
- }
- }
- */
- let AiLogo = event.target.childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('svg')[0].getAttribute("class"); // find the event when the AI logo will be inserted - class -> 'h-6 w-6'
- if (AiLogo === 'h-6 w-6'){ //now swap the logo with the custom logo
- let elementsSVG = document.querySelectorAll('.flex.flex-col.relative.items-end svg');
- elementsSVG.forEach(function(elementSVG) {
- var imgElement = document.createElement("img");
- imgElement.src = link;
- if(circle){imgElement.style.borderRadius = "14px";}
- if(shadow){imgElement.style.boxShadow = "0 2px 4px rgba(0,0,0,6)";}
- elementSVG.parentNode.replaceChild(imgElement, elementSVG);
- });
- let elementsRound = document.querySelectorAll('.relative.p-1.rounded-sm.text-white.flex.items-center.justify-center');
- elementsRound.forEach(function(elementRound) {
- elementRound.style.padding = '0';
- if(circle){elementRound.style.borderRadius = "14px";}
- });
- }
- /*
- try {
- let AiAnswer = event.target.childNodes[0].childNodes[1].childNodes[0].getElementsByTagName('div')[0].getAttribute("class"); //find the event when the AI gives an answer
- } catch (event) {
- if (event.name === 'TypeError') { //element doesnt exist yet (undefined) - wait for the element to be created
- } else {
- throw event; // re-throw the error
- }
- }
- */
- let AiAnswer = event.target.childNodes[0].childNodes[1].childNodes[0].getElementsByTagName('div')[0].getAttribute("class"); //find the event when the AI gives an answer
- if (AiAnswer === 'min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap'){
- //alert (event.relatedNode.innerHTML);
- let collectionA = document.getElementsByClassName('w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-50 dark:bg-[#444654]'); //maybe that tag is different if you don't unse the dark theme!
- var cLL = collectionA.length;
- if (cLL > 0){
- var readcounter = 0;
- var countnochange = 0;
- var delay = 6000; //Delay for one loop = 6 seconds
- var cutstart = 0;
- var cutend = 0;
- var cut1 = 0;
- var cut2 = 0;
- var speakstring = '';
- var oldlenght = 0;
- var myLoop = setInterval(function() {
- var currentLL = collectionA[cLL-1].childNodes[0].childNodes[1].childNodes[0].childNodes[0].childNodes[0].innerHTML;
- currentLL = currentLL.substr(3,currentLL.length-2);
- if (currentLL.length > oldlenght){
- oldlenght = currentLL.length;
- countnochange = 0;
- }
- readcounter++;
- var posd = currentLL.lastIndexOf('.')+1;
- var posp = currentLL.lastIndexOf(':')+1;
- var pose = currentLL.lastIndexOf('!')+1;
- var posq = currentLL.lastIndexOf('?')+1;
- var posb = currentLL.lastIndexOf(',')+1;
- var posX = currentLL.lastIndexOf(' ')+1;
- console.log ('posd: '+posd+' posp: '+posp+' pose: '+pose+' posq: '+posq+' posb: '+posb+' posX: '+posX);
- if (posd > cut1) {cut1 = posd;}
- if (posp > cut1) {cut1 = posp;}
- if (pose > cut1) {cut1 = pose;}
- if (posq > cut1) {cut1 = posq;}
- if (posb > cut2) {cut2 = posb;}
- if (posX > cut2) {cut2 = posX;}
- if (posX-posb<20){cut2 = posb;}else{cut2 = posX;} //prefer cutting at ',' instead of the ' ' if the the ',' is less than 20 chars away.. for fluent speaking
- if (cut2>cut1){cutend = cut2;}else{cutend = cut1;} //prefer .:!?
- console.log ('----------------------------------------------------------');
- console.log ('start: '+cutstart);
- console.log ('stop: '+cutend);
- var diff = oldlenght - cutend;
- console.log ('lenght: '+oldlenght);
- console.log ('diff: '+diff);
- if (readcounter === 1){
- speakstring = currentLL.substr(cutstart, cutend);
- speakstring = speakstring.replaceAll(/(<([^>]+)>)/ig,' '); //replace all tags with ' '
- }else{
- var fixend = cutend - diff;
- console.log ('fixing end to: '+fixend);
- speakstring = currentLL.substr(cutstart, fixend); //WTF!!!!
- speakstring = speakstring.substr(0, (speakstring.length - diff));
- speakstring = speakstring.replaceAll(/(<([^>]+)>)/ig,' ');
- }
- console.log ('readcounter:'+readcounter);
- console.log ('speakstring:'+speakstring);
- console.log ('----------------------------------------------------------');
- const synth = window.speechSynthesis;
- //const voices = window.speechSynthesis.getVoices();
- //console.log ('voices:'+voices.length);
- //const lastVoice = voices[2];
- //console.log ('voice:'+lastVoice.name);
- //const lastVoice = voices[voices.length - 1];
- const utterThis2 = new SpeechSynthesisUtterance(speakstring);
- //utterThis2.voice = lastVoice;
- utterThis2.voice = window.speechSynthesis.getVoices().find(voice => voice.voiceURI === voiceInEl.value);
- utterThis2.pitch = pitchInEl.value;
- utterThis2.rate = rateInEl.value;
- utterThis2.volume = volumeInEl.value;
- synth.speak(utterThis2);
- cutstart = cutend; //for next loop cycle
- if (currentLL.length === oldlenght){ // no change in text AI finisched writeing
- countnochange++;
- console.log ('count answer no change: '+countnochange);
- if (countnochange > 7){ //aftere 7 loops stop checking for changed answer
- clearInterval(myLoop);
- console.log ('count answer no change: '+countnochange);
- console.log ('stoped checking for answerchange');
- countnochange = 0;
- }
- }
- }, delay);
- }
- } //end answer
- });
- //Code from: https://codersblock.com/blog/javascript-text-to-speech-and-its-many-quirks/
- // grab the UI elements to work with
- //const textEl = document.getElementById('text');
- const voiceInEl = document.getElementById('voice');
- const pitchInEl = document.getElementById('pitch');
- const rateInEl = document.getElementById('rate');
- const volumeInEl = document.getElementById('volume');
- const pitchOutEl = document.querySelector('output[for="pitch"]');
- const rateOutEl = document.querySelector('output[for="rate"]');
- const volumeOutEl = document.querySelector('output[for="volume"]');
- //const speakEl = document.getElementById('speak');
- // add UI event handlers
- pitchInEl.addEventListener('change', updateOutputs);
- rateInEl.addEventListener('change', updateOutputs);
- volumeInEl.addEventListener('change', updateOutputs);
- //speakEl.addEventListener('click', speakText);
- // update voices immediately and whenever they are loaded
- updateVoices();
- window.speechSynthesis.onvoiceschanged = updateVoices;
- function updateOutputs() {
- // display current values of all range inputs
- pitchOutEl.textContent = pitchInEl.value;
- rateOutEl.textContent = rateInEl.value;
- volumeOutEl.textContent = volumeInEl.value;
- }
- function updateVoices() {
- // add an option for each available voice that isn't already added
- window.speechSynthesis.getVoices().forEach(voice => {
- const isAlreadyAdded = [...voiceInEl.options].some(option => option.value === voice.voiceURI);
- if (!isAlreadyAdded) {
- const option = new Option(voice.name, voice.voiceURI, voice.default, voice.default);
- voiceInEl.add(option);
- }
- });
- }
- /*
- let textelements = document.querySelectorAll('.flex.flex-col.w-full.py-2');
- let element = textelements[0];
- let textarea = element.querySelector('textarea');
- textarea.value = textinput;
- */
- /*
- document.addEventListener('DOMContentLoaded', function() {
- });
- */
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址