安装

安装 livego

方法一:使用云服务器+Docker

livego 是一个非常简单易配置的直播服务端,采用 Golang 编写,能够轻易部署在各种环境下。

开源地址:

https://github.com/gwuhaolin/livego

采用一键安装就行了,配置忽略。

docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -p 8090:8090 -d gwuhaolin/livego

需要注意,docker 内的版本更新不及时,有的功能没有支持如 https,如果需要最新版本,请自行编译 master 分支。

方法二:使用雨云云应用

通过雨云一键部署

获取推流的 key

curl http://IP:8090/control/get?room=movie
<
{"status":200,"data":"rfBd56ti2********************************5KLkIZ9PYk"}

获取到的 key 将在你的 OBS 推流时使用。

部署网站前端程序

将文件写入到index.html

然后随便找一个Nginx丢上去

基础版:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">
    <title>Live broadcast for you</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap-grid.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <style>
        body { position: fixed; height: 100%;
        background-color: #3e3e3e; }
        #videoElement{
            width:100%;
            height:320px;
        }
        .controls{margin-top: 15px;}
        .controls button{
            padding: 6px 18px;
        }
    </style>
</head>
<body>
    <div class="mainContainer">
        <video id="videoElement" class="centeredVideo" controls autoplay >Your browser is too old which doesn't support HTML5 video.</video>
    </div>
    <div class="controls">
        <!--<button onclick="flv_load()">加载</button>-->
        <button onclick="flv_start()">开始</button>
        <button onclick="flv_pause()">暂停</button>
        <button onclick="flv_destroy()">停止</button>
        <br>
        <br>
        <input style="width:100px" type="text" name="seekpoint" />
        <button onclick="flv_seekto()">跳转</button>
    </div>
    <script>
        var player = document.getElementById('videoElement');
        if (flvjs.isSupported()) {
            var flvPlayer = flvjs.createPlayer({
                type: 'flv',
                url: 'http://IP:7001/live/movie.flv'<!--更改这里的IP为你fu'wu'q服务器IP-->
            });
            flvPlayer.attachMediaElement(videoElement);
            flvPlayer.load();
        }

        function flv_start() {
            player.play();
        }

        function flv_pause() {
            player.pause();
        }

        function flv_destroy() {
            player.pause();
            player.unload();
            player.detachMediaElement();
            player.destroy();
            player = null;
        }

        function flv_seekto() {
            player.currentTime = parseFloat(document.getElementsByName('seekpoint')[0].value);
        }
    </script>
</body>
</html>

美化版:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>爱💤是天赋の直播</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <!-- 引入flv.js -->
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.js"></script>
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36BFFA',
                        dark: '#1E1E2E',
                        darker: '#141420',
                        light: '#E2E8F0'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .backdrop-blur {
                backdrop-filter: blur(8px);
            }
            .transition-transform {
                transition-property: transform;
                transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
                transition-duration: 150ms;
            }
        }
    </style>
</head>
<body class="bg-darker font-inter text-light min-h-screen flex flex-col">
    <!-- 顶部导航栏 -->
    <header class="bg-dark/80 backdrop-blur border-b border-gray-800 px-4 py-3 shadow-md">
        <div class="container mx-auto flex justify-between items-center">
            <div class="flex items-center space-x-2">
                <i class="fa fa-play-circle text-primary text-2xl"></i>
                <h1 class="text-xl font-bold text-white">爱💤是天赋の直播</h1>
            </div>

            <button class="md:hidden text-2xl">
                <i class="fa fa-bars"></i>
            </button>
        </div>
    </header>

    <!-- 主内容区 -->
    <main class="flex-grow container mx-auto px-4 py-6 md:py-10">
        <div class="max-w-6xl mx-auto">
            <!-- 视频标题和信息 -->
<!--            <div class="mb-6">
                <h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-white text-shadow mb-2">
                    爱💤是天赋の直播
                </h2>

            </div> -->

            <!-- 视频播放器容器 -->
            <div class="relative rounded-xl overflow-hidden shadow-2xl bg-black mb-6 transform transition-all duration-300 hover:shadow-primary/20">
                <video id="videoElement" class="w-full aspect-video object-contain" controls autoplay>
                    您的浏览器不支持HTML5视频播放。
                </video>
                
                <!-- 直播指示器 -->
                <div class="absolute top-4 left-4 bg-red-600 text-white text-xs font-bold px-3 py-1 rounded-full flex items-center">
                    <span class="w-2 h-2 bg-white rounded-full mr-2 animate-pulse"></span>
                    直播中
                </div>
            </div>

            <!-- 控制区域 -->
            <div class="bg-dark rounded-xl p-6 shadow-lg border border-gray-800">
                <h3 class="text-lg font-semibold mb-4 text-white">直播控制</h3>
                
                <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
                    <button onclick="flv_start()" class="flex items-center justify-center space-x-2 bg-primary hover:bg-primary/90 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                        <i class="fa fa-play"></i>
                        <span>开始</span>
                    </button>
                    
                    <button onclick="flv_pause()" class="flex items-center justify-center space-x-2 bg-gray-700 hover:bg-gray-600 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                        <i class="fa fa-pause"></i>
                        <span>暂停</span>
                    </button>
                    
                    <button onclick="flv_destroy()" class="flex items-center justify-center space-x-2 bg-red-600 hover:bg-red-700 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                        <i class="fa fa-stop"></i>
                        <span>停止</span>
                    </button>
                </div>
                
                <!-- 进度跳转控制 -->
                <div class="flex flex-col sm:flex-row items-start sm:items-center gap-3">
                    <label for="seekpoint" class="text-gray-400 whitespace-nowrap">跳转到指定位置(秒):</label>
                    <div class="flex-grow flex gap-3 w-full">
                        <input type="number" id="seekpoint" name="seekpoint" 
                            class="flex-grow bg-darker border border-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary/50"
                            placeholder="输入时间">
                        <button onclick="flv_seekto()" 
                            class="bg-secondary hover:bg-secondary/90 text-dark font-medium py-2 px-6 rounded-lg transition-all duration-200">
                            跳转
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-dark border-t border-gray-800 py-6 mt-10">
        <div class="container mx-auto px-4 text-center text-gray-500 text-sm">
            <p>© 2025 爱💤是天赋 版权所有</p>

        </div>
    </footer>

    <script>
        var player = document.getElementById('videoElement');
        if (flvjs.isSupported()) {
            var flvPlayer = flvjs.createPlayer({
                type: 'flv',
                url: 'http://156.245.244.142:7001/live/movie.flv'
            });
            flvPlayer.attachMediaElement(videoElement);
            flvPlayer.load();
            
            // 模拟观众数量更新
            setInterval(() => {
                const countEl = document.getElementById('viewer-count');
                const current = parseInt(countEl.textContent);
                const change = Math.floor(Math.random() * 11) - 5; // -5 到 +5 之间的随机变化
                const newCount = Math.max(1, current + change);
                countEl.textContent = newCount.toLocaleString() + ' 观众';
            }, 5000);
        }

        function flv_start() {
            player.play();
            showNotification('直播已开始', 'success');
        }

        function flv_pause() {
            player.pause();
            showNotification('直播已暂停', 'info');
        }

        function flv_destroy() {
            player.pause();
            player.unload();
            player.detachMediaElement();
            player.destroy();
            player = null;
            showNotification('直播已停止', 'warning');
        }

        function flv_seekto() {
            const input = document.getElementById('seekpoint');
            const time = parseFloat(input.value);
            
            if (!isNaN(time) && player) {
                player.currentTime = time;
                showNotification(`已跳转到 ${time} 秒`, 'success');
            } else {
                showNotification('请输入有效的时间', 'error');
            }
        }

        // 显示通知提示
        function showNotification(message, type = 'info') {
            // 创建通知元素
            const notification = document.createElement('div');
            
            // 设置样式和内容
            let bgColor, icon;
            switch(type) {
                case 'success':
                    bgColor = 'bg-green-500';
                    icon = 'fa-check-circle';
                    break;
                case 'error':
                    bgColor = 'bg-red-500';
                    icon = 'fa-exclamation-circle';
                    break;
                case 'warning':
                    bgColor = 'bg-yellow-500';
                    icon = 'fa-exclamation-triangle';
                    break;
                default:
                    bgColor = 'bg-blue-500';
                    icon = 'fa-info-circle';
            }
            
            notification.className = `fixed bottom-4 right-4 ${bgColor} text-white px-4 py-3 rounded-lg shadow-lg transform translate-y-10 opacity-0 transition-all duration-300 flex items-center space-x-2 z-50`;
            notification.innerHTML = `<i class="fa ${icon}"></i><span>${message}</span>`;
            
            // 添加到页面
            document.body.appendChild(notification);
            
            // 显示动画
            setTimeout(() => {
                notification.classList.remove('translate-y-10', 'opacity-0');
            }, 10);
            
            // 3秒后隐藏
            setTimeout(() => {
                notification.classList.add('translate-y-10', 'opacity-0');
                setTimeout(() => {
                    notification.remove();
                }, 300);
            }, 3000);
        }
    </script>
</body>
</html>

带评论版(基于Twikoo):

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>爱💤是天赋の直播</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <!-- 引入flv.js -->
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.js"></script>
    <!-- 引入twikoo评论系统 -->
    <script src="https://cdn.jsdelivr.net/npm/twikoo@1.6.44/dist/twikoo.all.min.js"></script>
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36BFFA',
                        dark: '#1E1E2E',
                        darker: '#141420',
                        light: '#E2E8F0',
                        comment: '#2A2A3C'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .backdrop-blur {
                backdrop-filter: blur(8px);
            }
            .transition-all-300 {
                transition: all 300ms ease-in-out;
            }
            .avatar-hover {
                transition: transform 0.3s ease, box-shadow 0.3s ease;
            }
            .avatar-hover:hover {
                transform: scale(1.05);
                box-shadow: 0 0 10px rgba(22, 93, 255, 0.3);
            }
        }
    </style>
</head>
<body class="bg-darker font-inter text-light min-h-screen flex flex-col">
    <!-- 顶部导航栏 -->
    <header class="bg-dark/80 backdrop-blur border-b border-gray-800 px-4 py-3 shadow-md sticky top-0 z-40">
        <div class="container mx-auto flex justify-between items-center">
            <div class="flex items-center space-x-2">
                <i class="fa fa-play-circle text-primary text-2xl"></i>
                <h1 class="text-xl font-bold text-white">爱💤是天赋の直播</h1>
            </div>

            <div class="hidden md:flex items-center space-x-6">

                <div class="flex items-center text-gray-400">
                    <i class="fa fa-clock-o mr-2"></i>
                    <span id="live-duration">00:00:00</span>
                </div>
            </div>

            <button class="md:hidden text-2xl">
                <i class="fa fa-bars"></i>
            </button>
        </div>
    </header>

    <!-- 主内容区 -->
    <main class="flex-grow container mx-auto px-4 py-6 md:py-10">
        <div class="max-w-7xl mx-auto">
            <!-- 视频标题和信息 -->
            <div class="mb-6">
                <h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-white text-shadow mb-2">
                    爱💤是天赋の直播
                </h2>
                <div class="flex flex-wrap items-center gap-4 text-gray-400 text-sm md:hidden">

                    <div class="flex items-center">
                        <i class="fa fa-clock-o mr-2"></i>
                        <span id="live-duration-mobile">00:00:00</span>
                    </div>
                </div>
            </div>

            <!-- 视频和评论区容器 -->
            <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
                <!-- 视频和控制区 - 占据2/3宽度 -->
                <div class="lg:col-span-2 space-y-6">
                    <!-- 视频播放器容器 -->
                    <div class="relative rounded-xl overflow-hidden shadow-2xl bg-black transform transition-all duration-300 hover:shadow-primary/20">
                        <video id="videoElement" class="w-full aspect-video object-contain" controls autoplay>
                            您的浏览器不支持HTML5视频播放。
                        </video>
                        
                        <!-- 直播指示器 -->
                        <div class="absolute top-4 left-4 bg-red-600 text-white text-xs font-bold px-3 py-1 rounded-full flex items-center">
                            <span class="w-2 h-2 bg-white rounded-full mr-2 animate-pulse"></span>
                            直播中
                        </div>
                    </div>

                    <!-- 控制区域 -->
                    <div class="bg-dark rounded-xl p-6 shadow-lg border border-gray-800">
                        <h3 class="text-lg font-semibold mb-4 text-white">直播控制</h3>
                        
                        <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
                            <button onclick="flv_start()" class="flex items-center justify-center space-x-2 bg-primary hover:bg-primary/90 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                                <i class="fa fa-play"></i>
                                <span>开始</span>
                            </button>
                            
                            <button onclick="flv_pause()" class="flex items-center justify-center space-x-2 bg-gray-700 hover:bg-gray-600 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                                <i class="fa fa-pause"></i>
                                <span>暂停</span>
                            </button>
                            
                            <button onclick="flv_destroy()" class="flex items-center justify-center space-x-2 bg-red-600 hover:bg-red-700 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105">
                                <i class="fa fa-stop"></i>
                                <span>停止</span>
                            </button>
                        </div>
                        
                        <!-- 进度跳转控制 -->
                        <div class="flex flex-col sm:flex-row items-start sm:items-center gap-3">
                            <label for="seekpoint" class="text-gray-400 whitespace-nowrap">跳转到指定位置(秒):</label>
                            <div class="flex-grow flex gap-3 w-full">
                                <input type="number" id="seekpoint" name="seekpoint" 
                                    class="flex-grow bg-darker border border-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary/50"
                                    placeholder="输入时间">
                                <button onclick="flv_seekto()" 
                                    class="bg-secondary hover:bg-secondary/90 text-dark font-medium py-2 px-6 rounded-lg transition-all duration-200">
                                    跳转
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 评论区 - 占据1/3宽度 -->
                <div class="lg:col-span-1">
                    <div class="bg-dark rounded-xl shadow-lg border border-gray-800 h-full flex flex-col">
                        <div class="p-4 border-b border-gray-800 flex justify-between items-center">
                            <h3 class="text-lg font-semibold text-white flex items-center">
                                <i class="fa fa-comments text-primary mr-2"></i>
                                观众评论
                            </h3>
                            <!--  <span id="comment-count" class="bg-gray-700 text-gray-300 text-sm px-2 py-1 rounded-full">0 条评论</span>-->
                        </div>
                        
                        <!-- 评论列表区域 -->
                        <div id="tcomment" class="flex-grow overflow-y-auto p-4 flex flex-col items-center w-full">
                            <!-- 评论将通过twikoo加载 -->
                            <div class="flex justify-center items-center h-40 text-gray-500 w-full">
                                <div class="text-center">
                                    <i class="fa fa-spinner fa-spin text-2xl mb-2"></i>
                                    <p>加载评论中...</p>
                                </div>
                            </div>
                        </div>
                        
                        <!-- 评论输入区域 -->
                        <div class="p-4 border-t border-gray-800 bg-comment/50 w-full">
                            <div id="twikoo-form" class="twikoo-form mx-auto max-w-md"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-dark border-t border-gray-800 py-6 mt-10">
        <div class="container mx-auto px-4 text-center text-gray-500 text-sm">
            <p>© 2025 爱💤是天赋 版权所有</p>
        </div>
    </footer>

    <script>
        // 从配置文件加载配置
        let config = {
            flvUrl: "http:///your-live-ip:7001/live/movie.flv",
            twikooUrl: "https://your-twikoo-url.example.com"
        };
        
        // 加载配置文件
        fetch('config.json')
            .then(response => response.json())
            .then(data => {
                config = { ...config, ...data };
                initPlayer();
                initComments();
            })
            .catch(error => {
                console.error('加载配置文件失败,使用默认配置:', error);
                initPlayer();
                initComments();
            });

        let flvPlayer = null;
        let liveStartTime = new Date();
        let viewerCount = 1234;
        
        // 初始化视频播放器
        function initPlayer() {
            const player = document.getElementById('videoElement');
            if (flvjs.isSupported() && config.flvUrl) {
                flvPlayer = flvjs.createPlayer({
                    type: 'flv',
                    url: config.flvUrl
                });
                flvPlayer.attachMediaElement(player);
                flvPlayer.load();
                
                // 直播开始时间
                liveStartTime = new Date();
                
                // 更新直播时长
                setInterval(updateLiveDuration, 1000);
                
                // 模拟观众数量更新
                setInterval(updateViewerCount, 5000);
            } else {
                showNotification('您的浏览器不支持FLV视频播放', 'error');
            }
        }
        
        // 初始化评论系统,优化头像显示
        function initComments() {
            if (config.twikooUrl) {
                twikoo.init({
                    envId: config.twikooUrl,
                    el: '#tcomment',
                    path: window.location.pathname,
                    // 自定义样式,重点优化头像显示,兼容Twikoo机制
                    customStyle: `
                        /* 评论容器样式 */
                        #tcomment {
                            width: 100% !important;
                            display: flex !important;
                            flex-direction: column !important;
                            align-items: center !important;
                        }
                        
                        /* 评论项样式 */
                        .tk-comment {
                            background-color: #2A2A3C !important;
                            border-radius: 8px !important;
                            padding: 15px !important;
                            margin-bottom: 15px !important;
                            border: none !important;
                            box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
                            width: 100% !important;
                            max-width: 600px !important;
                            display: flex !important;
                            align-items: flex-start !important;
                        }
                        
                        /* 头像容器 - 兼容Twikoo默认结构 */
                        .tk-avatar-container {
                            margin-right: 12px !important;
                            flex-shrink: 0 !important;
                        }
                        
                        /* 头像样式优化 - 兼容Twikoo头像机制 */
                        .tk-avatar {
                            width: 48px !important;
                            height: 48px !important;
                            border-radius: 50% !important;
                            object-fit: cover !important; /* 确保图片正确缩放 */
                            border: 2px solid rgba(22, 93, 255, 0.2) !important;
                            box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
                            transition: all 0.3s ease !important;
                        }
                        
                        /* 头像悬停效果 */
                        .tk-avatar:hover {
                            transform: scale(1.05) !important;
                            box-shadow: 0 0 10px rgba(22, 93, 255, 0.4) !important;
                            border-color: rgba(22, 93, 255, 0.5) !important;
                        }
                        
                        /* 处理默认头像和自定义头像的统一显示 */
                        .tk-avatar[src*="default-avatar"] {
                            background-color: #383850 !important;
                            display: flex !important;
                            align-items: center !important;
                            justify-content: center !important;
                            font-weight: bold !important;
                        }
                        
                        /* 评论内容样式 */
                        .tk-name {
                            color: #E2E8F0 !important;
                            font-weight: 600 !important;
                            margin-bottom: 5px !important;
                        }
                        .tk-content {
                            color: #CBD5E1 !important;
                            line-height: 1.6 !important;
                            margin-bottom: 8px !important;
                        }
                        .tk-time {
                            color: #718096 !important;
                            font-size: 12px !important;
                        }
                        
                        /* 评论输入区域样式 */
                        .tk-comment-box {
                            border-top: 1px solid #383850 !important;
                            padding-top: 15px !important;
                            width: 100% !important;
                            max-width: 600px !important;
                        }
                        
                        /* 输入框中的头像预览 */
                        .tk-editor-avatar {
                            width: 36px !important;
                            height: 36px !important;
                            border-radius: 50% !important;
                            margin-right: 8px !important;
                            object-fit: cover !important;
                        }
                        
                        /* 版权信息居中 */
                        .tk-powered-by {
                            text-align: center !important;
                            margin: 15px auto !important;
                            display: block !important;
                            color: #718096 !important;
                            font-size: 12px !important;
                        }
                    `,
                    onCommentLoaded: function (count) {
                        document.getElementById('comment-count').textContent = `${count} 条评论`;
                        
                        // 处理头像加载失败的情况,显示默认头像
                        setTimeout(() => {
                            const avatars = document.querySelectorAll('.tk-avatar');
                            avatars.forEach(avatar => {
                                // 监听头像加载失败事件
                                avatar.addEventListener('error', function() {
                                    // 加载失败时显示默认头像
                                    this.src = 'https://img.shihanya666.me/uploads/2025/10/08/2025/10/08/1759924421.webp';
                                    this.alt = '用户头像';
                                });
                                
                                // 确保默认头像也有良好的显示效果
                                if (this.src.includes('default-avatar') || !this.src) {
                                    this.src = 'https://img.shihanya666.me/uploads/2025/10/08/2025/10/08/1759924421.webp';
                                    this.alt = '用户头像';
                                }
                            });
                        }, 500);
                    }
                });
            } else {
                document.getElementById('tcomment').innerHTML = '<div class="text-center p-6 text-gray-500"><i class="fa fa-exclamation-circle mr-2"></i>评论功能未配置</div>';
            }
        }

        // 直播控制函数
        function flv_start() {
            if (flvPlayer) {
                flvPlayer.play();
                showNotification('直播已开始', 'success');
            }
        }

        function flv_pause() {
            if (flvPlayer) {
                flvPlayer.pause();
                showNotification('直播已暂停', 'info');
            }
        }

        function flv_destroy() {
            if (flvPlayer) {
                flvPlayer.pause();
                flvPlayer.unload();
                flvPlayer.detachMediaElement();
                flvPlayer.destroy();
                flvPlayer = null;
                showNotification('直播已停止', 'warning');
            }
        }

        function flv_seekto() {
            const input = document.getElementById('seekpoint');
            const time = parseFloat(input.value);
            
            if (!isNaN(time) && flvPlayer) {
                flvPlayer.currentTime = time;
                showNotification(`已跳转到 ${time} 秒`, 'success');
            } else {
                showNotification('请输入有效的时间', 'error');
            }
        }

        // 更新直播时长
        function updateLiveDuration() {
            const now = new Date();
            const durationMs = now - liveStartTime;
            const seconds = Math.floor((durationMs / 1000) % 60);
            const minutes = Math.floor((durationMs / (1000 * 60)) % 60);
            const hours = Math.floor(durationMs / (1000 * 60 * 60));
            
            const durationStr = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
            document.getElementById('live-duration').textContent = durationStr;
            document.getElementById('live-duration-mobile').textContent = durationStr;
        }

        // 更新观众数量
        function updateViewerCount() {
            const change = Math.floor(Math.random() * 11) - 3; // -3 到 +7 之间的随机变化
            viewerCount = Math.max(1, viewerCount + change);
            const countStr = viewerCount.toLocaleString() + ' 观众';
            document.getElementById('viewer-count').textContent = countStr;
            document.getElementById('viewer-count-mobile').textContent = countStr;
        }

        // 显示通知提示
        function showNotification(message, type = 'info') {
            const notification = document.createElement('div');
            
            let bgColor, icon;
            switch(type) {
                case 'success':
                    bgColor = 'bg-green-500';
                    icon = 'fa-check-circle';
                    break;
                case 'error':
                    bgColor = 'bg-red-500';
                    icon = 'fa-exclamation-circle';
                    break;
                case 'warning':
                    bgColor = 'bg-yellow-500';
                    icon = 'fa-exclamation-triangle';
                    break;
                default:
                    bgColor = 'bg-blue-500';
                    icon = 'fa-info-circle';
            }
            
            notification.className = `fixed bottom-4 right-4 ${bgColor} text-white px-4 py-3 rounded-lg shadow-lg transform translate-y-10 opacity-0 transition-all duration-300 flex items-center space-x-2 z-50`;
            notification.innerHTML = `<i class="fa ${icon}"></i><span>${message}</span>`;
            
            document.body.appendChild(notification);
            
            setTimeout(() => {
                notification.classList.remove('translate-y-10', 'opacity-0');
            }, 10);
            
            setTimeout(() => {
                notification.classList.add('translate-y-10', 'opacity-0');
                setTimeout(() => {
                    notification.remove();
                }, 300);
            }, 3000);
        }
    </script>
</body>
</html>

config.json

{
    "flvUrl": "http://IP:7001/live/movie.flv",
    "twikooUrl": "https://twikoo.online"
}

推流

本地使用 OBS 进行播放采集推流

OBS 配置如下:

服务器直接填写你的服务器 IP 和端口,记得开放防火墙规则。

格式:rtmp://ip:1935/live/

密钥在前面创建 livego 服务时获取的。

保存后,就可以进行推流了。

服务器推流

如果你没有其他电脑,可以通过服务器进行推流,前提是服务器有对应的视频文件。

ffmpeg -re -i demo.flv -c copy -f flv rtmp://localhost:1935/live/{channelkey}

ffmpeg 也可以通过 docker 安装的,localhost 可以改成 docker 网关 IP 即可。