Auto Play Audio Sequentially

访问指定 URL 获取音频并自动播放,确保按顺序播放

目前為 2024-03-12 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Auto Play Audio Sequentially
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  访问指定 URL 获取音频并自动播放,确保按顺序播放
// @author       Your Name
// @match        *://*/*
// @grant        none
// ==/UserScript==
(function() {
    'use strict';

    // 初始 URL
    const initialUrl = 'http://localhost:9880?text=你好,我是七七,是个小僵尸&text_lang=中文&ref_audio_path=./qiqi3.mp3&prompt_text=刮大风了…_拉手…拉手!要、要被吹跑了!…&prompt_lang=中文&sweight=SoVITS_weights/qiqi_e8_s136.pth&gweight=GPT_weights/qiqi-e15.ckpt';

    // 当前 URL
    let currentUrl = initialUrl;

    // 存储待播放的音频URL队列
    const audioQueue = [];

    // 是否有音频正在播放
    let isPlaying = false;

    // 存储已经绑定过按钮的 div 元素
    const boundDivs = new Set();

    // 检测并插入播放按钮的函数
    function checkAndInsertPlayButton() {
        const divElements = document.querySelectorAll('div');

        divElements.forEach(div => {
            if (div.getAttribute('dir') === 'auto' && !boundDivs.has(div)) {
                const playButton = document.createElement('button');
                playButton.textContent = 'Play Audio';
                div.parentNode.insertBefore(playButton, div.nextSibling);

                playButton.addEventListener('click', async function() {
                    const text = div.textContent.trim();
                    const quotes = extractQuotes(text);
                    for (const quote of quotes) {
                        await fetchAudioAndAddToQueue(updateUrlWithText(currentUrl, quote));
                    }
                });

                boundDivs.add(div); // 将已经绑定过按钮的 div 元素添加到集合中
            }
        });
    }

    // 每隔 5 秒检测一次 div 元素
    setInterval(checkAndInsertPlayButton, 5000);

    // 获取音频并添加到播放队列
    async function fetchAudioAndAddToQueue(url) {
        try {
            const response = await fetch(url);
            const blob = await response.blob();
            const audioUrl = window.URL.createObjectURL(blob);
            audioQueue.push(audioUrl);
            playNextAudio();
        } catch (error) {
            console.error('获取音频失败:', error);
        }
    }

    // 播放队列中的下一个音频
    function playNextAudio() {
        if (isPlaying || audioQueue.length === 0) {
            return;
        }
        isPlaying = true;
        const audioUrl = audioQueue.shift(); // 获取并移除队列中的第一个音频URL
        const audio = new Audio(audioUrl);
        audio.play();
        audio.onended = function() {
            isPlaying = false;
            playNextAudio(); // 播放完毕后继续播放下一个
        };
    }

    // 提取文本中的双引号内容
    function extractQuotes(text) {
        const quotes = [];
        const regex = /“(.*?)”/g;
        const regex2 = /"(.*?)"/g;
        let text2=text;
        let match;
        while ((match = regex.exec(text)) !== null) {
            quotes.push(match[1]);
        }
        let match2;
        while ((match2 = regex2.exec(text2)) !== null) {
            quotes.push(match2[1]);
        }
        return quotes;
    }

    // 更新 URL 中的 text 参数
    function updateUrlWithText(url, text) {
        const urlObj = new URL(url);
        urlObj.searchParams.set('text', text);
        return urlObj.toString();
    }
})();