小鱼塘--自说自话的地方

  • 小玩意
  • 小想法
记录自己技术和想法地方
  1. 首页
  2. AI
  3. 正文

美团tabbit使用脚本实现小宇宙播放记录

29 4 月, 2026 5点热度 0人点赞 0条评论
内容目录

背景

小宇宙博客网页不能登陆,没有记录,我很久之前想写一个脚本解决问题

用途

网页播放博客的时候,关闭网页再次打会,点击播放会从上次播放地方继续

过程

  1. 通过美团tabbit AI直接生成脚本
  2. 修复几次发现有问题,懒的跟AI交换
  3. 分析代码,我知道大概逻辑,因为以前不了解H5 播放器的操作知识点
  4. 重新手写一份

脚本

(function () {

    console.log("脚本加载中")
    function OnceRun() {
        if (!window.__podcastProgressRecorder) {
            window.__podcastProgressRecorder = true
            return true
        } else {
            return false
        }
    }

    if (!OnceRun()) {
        console.warn("脚本不需要重复加载")
        return;
    }

    //定义属性
    var save_timer;
    var RECORD_PRIFX = "_YU_RECORD_PROCESS_"
    var is_need_restore = true
    var target_time                             //目标播放的时间
    let save_interval                           //保存的定时器
    var URL_KEY = "episode"

    console.log("===============页面加载了=================")
    //第一次加载,初始化
    async function initSub() {
        if (window.location.pathname.indexOf(URL_KEY) > 0) {
            let audio = await waitAudio();
            if (audio == null) {
                console.log("声音元素没有找到")
                return
            } else {
                console.log("声音元素")
                console.info(audio)
            }

            bindAutioEvent(audio);
        } else {
            console.log("当前url,不进行恢复和保存")
        }
    }

    function init() {
        console.log("进行初始化")
        console.log(document.readyState)
        if (document.readyState == "loading") {
            window.addEventListener("DOMContentLoaded", initSub)
        } else {
            initSub()
        }
    }

    //等待声音audio
    async function waitAudio(maxRetries = 100) {
        console.log("正在查找声音元素")
        return new Promise((resolve) => {
            let retries = 0;
            const interval = setInterval(() => {
                const audio = document.querySelector('audio');
                if (audio) {
                    clearInterval(interval);
                    resolve(audio);
                }
                retries++;
                if (retries >= maxRetries) {
                    clearInterval(interval);
                    resolve(null);
                }
            }, 200);
        });
    }

    //获取记录
    function getStoreageRecord() {
        let key = RECORD_PRIFX + window.location.pathname
        return localStorage.getItem(key)
    }

    //保存记录
    function saveRecord(time) {
        let key = RECORD_PRIFX + window.location.pathname
        if (window.location.pathname.indexOf("episode") >= 0) {
            console.log("save:" + key + " value:" + time)
            localStorage.setItem(key, time)
        } else {
            console.log("当前url,不保存进度")
        }
    }

    /**
     * 
     * @param audio {HTMLAudioElement}
     */
    function checkRestoreRecord(audio) {
        let r = getStoreageRecord()
        console.log("存放的值")
        console.info(r)
        if (r != undefined && r != null) {
            console.log("进行恢复设置")
            target_time = r
        }
    }

    /**
     * 
     * @param audio {HTMLAudioElement}
     */
    function autoRestoreRecord(audio) {
        console.log("进入 autoRestoreRecord")
        if (is_need_restore) {
            if (target_time) {

                let v = target_time - audio.currentTime
                if (v > 0 && v >= 5) {
                    console.log("正在恢复中")
                    console.log("-----------------:" + target_time + " current_time:" + audio.currentTime)
                    audio.currentTime = target_time
                } else {
                    console.log("恢复成功")
                    target_time = false
                    is_need_restore = false
                }
            }
        }
    }

    /**
     * 
     * @param audio {HTMLAudioElement} audio - HTML5 Audio 元素
     */
    function bindAutioEvent(audio) {
        if (!audio) return
        console.log("进行绑定声音元素")
        audio.addEventListener("play", () => {
            console.log("声音进行播放了")
            console.info(formatTime(audio.currentTime))
        })

        audio.addEventListener("pause", () => {
            console.log("暂停播放")
            console.info(formatTime(audio.currentTime))
        })

        audio.addEventListener("loadedmetadata", () => {
            console.log("loadedmetadata")
        })

        audio.addEventListener("playing", () => {
            console.log("播放中====>")
            autoRestoreRecord(audio)
        })

        audio.addEventListener("canplay", () => {
            console.log("canplay")
        })

        audio.addEventListener("seeked", () => {
            console.log("seeked")
        })

        if (is_need_restore) {
            checkRestoreRecord(audio)
        }

        createSaveInterval(audio)
    }

    // 格式化时间
    function formatTime(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins}:${secs.toString().padStart(2, '0')}`;
    }

    function createSaveInterval(audio) {
        if (save_interval) {
            clearInterval(save_interval)
            save_interval = false
        }

        save_interval = setInterval(() => {
            console.log("进入定时的器")
            if (audio) {
                console.log("is_need_resotre:" + is_need_restore + " target_time:" + target_time)
                if (is_need_restore == false || (is_need_restore == true && !target_time)) {
                    if (!audio.paused && !audio.ended && audio.currentTime > 0) {
                        saveRecord(audio.currentTime)
                    }
                }
            }else{
                console.log("audio 无效")
            }
        }, 1000);
    }

    //网页变化
    function onWebChange() {
        console.log("========网页进行变化了,进行重新初始化=======")
        is_need_restore = true; //重新初始化
        initSub()
    }

    init();

    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = function (...args) {
        console.log("push state ===>")
        originalPushState.apply(history, args);
        onWebChange();
    };

    history.replaceState = function (...args) {
        console.log("replaceState ===>")
        originalReplaceState.apply(history, args);
        onWebChange();
    };
})();

设置

  1. 打开我的妙招
  2. 点击右上角创建脚本
  3. 粘贴代码
  4. 设置自动运行和指定网址

指定网址:https://www.xiaoyuzhoufm.com/episode
这样子只有小宇宙博客界面详情才会触发,同时一定要打开每次自动运行,不然必须手动触发

总结

  1. AI 会减低创建脚本难度
  2. 复杂度增加AI 交流成本也会变更高,其实我不认为AI 编程是未来,虽然很多说AI 编程是未来,现在手写代码是古法编程,我反而觉得AI 编程 对于demo 或者小项目可以,对于很多项目是不合适,我反而觉得是邪修,一句话 这个世界没有银弹来解决一些事务
标签: 暂无
最后更新:29 4 月, 2026

小鱼儿

爱研究技术,爱玩LOL

点赞
< 上一篇

COPYRIGHT © 2022 小鱼塘. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

湘ICP备18005349号