ChatGPT 回答完成提示音(WebAudio 方式)

使用 Web Audio API 播放提示音,不依赖外链,避免无声,稳定可靠;每次回答后提醒一次。

目前為 2025-08-01 提交的版本,檢視 最新版本

// ==UserScript==
// @license      MIT

// @name         ChatGPT 回答完成提示音(WebAudio 方式)
// @namespace    https://github.com/xiaozhang
// @version      1.5
// @description  使用 Web Audio API 播放提示音,不依赖外链,避免无声,稳定可靠;每次回答后提醒一次。
// @author       小张
// @match        https://chatgpt.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    let lastContentLength = 0;
    let isAnswering = false;
    let hasAlerted = false;
    let lastAnswerId = null;
    let soundUnlocked = false;
    let audioCtx = null;

    // 解锁音频(需要用户首次点击)
    window.addEventListener('click', function unlockAudio() {
        if (!soundUnlocked) {
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            playBeep(); // 立即播放一个 beep 声以解锁
            soundUnlocked = true;
            console.log('🔓 音频权限已解锁');
        }
        window.removeEventListener('click', unlockAudio);
    });

    // 用 Web Audio 播放 Beep
    function playBeep() {
        if (!audioCtx) return;
        const oscillator = audioCtx.createOscillator();
        const gainNode = audioCtx.createGain();

        oscillator.type = 'sine'; // 正弦波
        oscillator.frequency.setValueAtTime(1000, audioCtx.currentTime); // 1kHz
        gainNode.gain.setValueAtTime(0.2, audioCtx.currentTime); // 音量

        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);

        oscillator.start();
        oscillator.stop(audioCtx.currentTime + 0.2); // 0.2 秒 beep
    }

    setInterval(() => {
        const chatContainer = document.querySelector('main');
        if (!chatContainer) return;

        const chatContents = chatContainer.querySelectorAll('[data-message-author-role="assistant"]');
        if (chatContents.length === 0) return;

        const lastContent = chatContents[chatContents.length - 1];
        const currentText = lastContent.innerText.trim();
        const currentLength = currentText.length;

        const currentId = lastContent.getAttribute('data-message-id') || lastContent.innerHTML.slice(0, 50);

        if (currentId !== lastAnswerId) {
            lastAnswerId = currentId;
            lastContentLength = 0;
            isAnswering = false;
            hasAlerted = false;
        }

        if (currentLength > lastContentLength + 5) {
            isAnswering = true;
            hasAlerted = false;
            lastContentLength = currentLength;
        } else if (isAnswering && !hasAlerted && currentLength === lastContentLength) {
            hasAlerted = true;
            isAnswering = false;
            playBeep();
        }

    }, 100);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址