您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Use Web Speech API to read aloud selected text or full page, with voice picker, speed & pitch sliders, plus minimize & close buttons
// ==UserScript== // @name Read Aloud with Voice, Speed & Pitch Controls // @namespace http://tampermonkey.net/ // @version 1.3 // @description Use Web Speech API to read aloud selected text or full page, with voice picker, speed & pitch sliders, plus minimize & close buttons // @author You // @match *://*/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; // --- UI Container --- const container = document.createElement("div"); Object.assign(container.style, { position: "fixed", bottom: "20px", right: "20px", background: "#222", color: "#fff", padding: "10px", borderRadius: "10px", zIndex: 9999, fontSize: "14px", display: "flex", flexDirection: "column", gap: "5px", width: "220px", fontFamily: "sans-serif" }); // --- Header with controls --- const header = document.createElement("div"); Object.assign(header.style, { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "5px" }); const title = document.createElement("span"); title.textContent = "Read Aloud"; title.style.fontWeight = "bold"; const controls = document.createElement("div"); // Minimize button const minimizeBtn = document.createElement("button"); minimizeBtn.textContent = "—"; Object.assign(minimizeBtn.style, { background: "transparent", color: "#fff", border: "none", cursor: "pointer", marginRight: "5px", fontSize: "16px" }); // Close button const closeBtn = document.createElement("button"); closeBtn.textContent = "✕"; Object.assign(closeBtn.style, { background: "transparent", color: "#fff", border: "none", cursor: "pointer", fontSize: "16px" }); controls.appendChild(minimizeBtn); controls.appendChild(closeBtn); header.appendChild(title); header.appendChild(controls); // --- Content container (collapsible) --- const content = document.createElement("div"); Object.assign(content.style, { display: "flex", flexDirection: "column", gap: "5px" }); // --- Voice Dropdown --- const voiceSelect = document.createElement("select"); Object.assign(voiceSelect.style, { padding: "5px", width: "100%" }); // --- Speed Slider --- const rateLabel = document.createElement("label"); rateLabel.textContent = "Speed: 1.0"; const rateSlider = document.createElement("input"); rateSlider.type = "range"; rateSlider.min = "0.5"; rateSlider.max = "2"; rateSlider.step = "0.1"; rateSlider.value = "1"; rateSlider.style.width = "100%"; rateSlider.addEventListener("input", () => { rateLabel.textContent = `Speed: ${rateSlider.value}`; }); // --- Pitch Slider --- const pitchLabel = document.createElement("label"); pitchLabel.textContent = "Pitch: 1.0"; const pitchSlider = document.createElement("input"); pitchSlider.type = "range"; pitchSlider.min = "0.5"; pitchSlider.max = "2"; pitchSlider.step = "0.1"; pitchSlider.value = "1"; pitchSlider.style.width = "100%"; pitchSlider.addEventListener("input", () => { pitchLabel.textContent = `Pitch: ${pitchSlider.value}`; }); // --- Button --- const btn = document.createElement("button"); btn.textContent = "🔊 Read Aloud"; Object.assign(btn.style, { padding: "8px", background: "#444", color: "#fff", border: "none", borderRadius: "6px", cursor: "pointer" }); // --- Assemble --- content.appendChild(voiceSelect); content.appendChild(rateLabel); content.appendChild(rateSlider); content.appendChild(pitchLabel); content.appendChild(pitchSlider); content.appendChild(btn); container.appendChild(header); container.appendChild(content); document.body.appendChild(container); // --- Voice Setup --- let voices = []; function populateVoices() { voices = speechSynthesis.getVoices(); voiceSelect.innerHTML = ""; voices.forEach((v, i) => { const option = document.createElement("option"); option.value = i; option.textContent = `${v.name} (${v.lang})`; voiceSelect.appendChild(option); }); } populateVoices(); speechSynthesis.onvoiceschanged = populateVoices; // --- Read Aloud Logic --- let utterance = null; btn.addEventListener("click", () => { const selectedText = window.getSelection().toString().trim(); const text = selectedText || document.body.innerText; if (speechSynthesis.speaking) { speechSynthesis.cancel(); btn.textContent = "🔊 Read Aloud"; } else { utterance = new SpeechSynthesisUtterance(text); // Apply voice, speed, pitch const selectedVoice = voices[voiceSelect.value]; if (selectedVoice) utterance.voice = selectedVoice; utterance.rate = parseFloat(rateSlider.value); utterance.pitch = parseFloat(pitchSlider.value); btn.textContent = "⏹ Stop"; speechSynthesis.speak(utterance); utterance.onend = () => { btn.textContent = "🔊 Read Aloud"; }; } }); // --- Minimize & Close logic --- let minimized = false; minimizeBtn.addEventListener("click", () => { minimized = !minimized; content.style.display = minimized ? "none" : "flex"; minimizeBtn.textContent = minimized ? "+" : "—"; }); closeBtn.addEventListener("click", () => { speechSynthesis.cancel(); container.remove(); }); })();