您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Read aloud the current article in FreshRSS or the text from a webpage using a custom TTS API
当前为
// ==UserScript== // @name RSS: FreshRSS Read Aloud // @namespace http://tampermonkey.net/ // @version 2.9 // @description Read aloud the current article in FreshRSS or the text from a webpage using a custom TTS API // @author Your Name // @match http://192.168.1.2:1030/* // @grant GM_xmlhttpRequest // ==/UserScript== (function() { 'use strict'; // Function to extract text from the webpage or FreshRSS article function extractText() { const isFreshRSS = document.querySelector('.flux_content') !== null; if (isFreshRSS) { const articleContent = document.querySelector('.flux.active.current .flux_content .text'); if (articleContent) { let text = articleContent.innerText.trim(); // Remove "Summarize" from the beginning and end if (text.startsWith('Summarize')) { text = text.substring('Summarize'.length).trim(); } if (text.endsWith('Summarize')) { text = text.substring(0, text.length - 'Summarize'.length).trim(); } return text; } } else { const elementsToRemove = document.querySelectorAll('script, style'); elementsToRemove.forEach(el => el.remove()); return document.body.innerText.trim(); } return null; } // Function to fetch and set audio source async function fetchAudioSource() { const text = extractText(); if (!text) { throw new Error('No text content found on the webpage.'); } const audioPlayer = document.getElementById('tts-audio'); const apiUrl = `http://192.168.1.2:1202/api/tts?download=true&shardLength=10000&thread=500&text=${encodeURIComponent(text)}`; return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', apiUrl, true); xhr.responseType = 'blob'; xhr.onload = function() { if (xhr.status === 200) { const blob = new Blob([xhr.response], { type: 'audio/mpeg' }); const url = URL.createObjectURL(blob); // Clean up old URL if it exists if (audioPlayer.dataset.blobUrl) { URL.revokeObjectURL(audioPlayer.dataset.blobUrl); } audioPlayer.dataset.blobUrl = url; audioPlayer.src = url; resolve(); } else { reject(new Error(`HTTP error! status: ${xhr.status}`)); } }; xhr.onerror = () => reject(new Error('Network request failed')); xhr.send(); }); } // Initialize the audio player function initializeAudioPlayer() { const container = document.createElement('div'); container.id = 'tts-audio-container'; container.style.cssText = 'position: fixed; top: 15px; left: 10px; z-index: 9999;'; const audioPlayer = document.createElement('audio'); audioPlayer.id = 'tts-audio'; audioPlayer.controls = true; audioPlayer.style.cssText = 'width: 50px; height: 20px; opacity: 0.3;'; audioPlayer.innerHTML = 'Your browser does not support the audio element.'; let isInitialPlay = true; audioPlayer.addEventListener('play', async (e) => { if (isInitialPlay) { e.preventDefault(); audioPlayer.pause(); try { await fetchAudioSource(); isInitialPlay = false; audioPlayer.play(); } catch (error) { console.error('Error fetching audio:', error); isInitialPlay = true; } } }); audioPlayer.addEventListener('ended', () => { if (audioPlayer.dataset.blobUrl) { URL.revokeObjectURL(audioPlayer.dataset.blobUrl); delete audioPlayer.dataset.blobUrl; } audioPlayer.src = ''; isInitialPlay = true; }); container.appendChild(audioPlayer); document.body.appendChild(container); } // Initialize the audio player initializeAudioPlayer(); })();