Livego: 部署一个简单直播网站服务!
安装
安装 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 即可。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

