当前位置:首页>python>PythonGui电视频道管理系统

PythonGui电视频道管理系统

  • 2026-10-11 06:23:16
PythonGui电视频道管理系统

📺 电视频道管理系统

Channel Manager Pro v1.0

一款基于 PyQt5 + MySQL + VLC 的全功能网络电视频道管理与播放一体化桌面应用

👤 作者信息

项目
内容
作者
杨一凡
微信号
ysp2338084
公众号
Python学在坚持
文件下载地址
链接: https://pan.baidu.com/s/12UO-AUkG8CxzgGxTu8HHfA?pwd=xzjc 提取码: xzjc 复制这段内容后打开百度网盘手机App,操作更方便哦


🌟 项目介绍

网络电视频道管理系统(Channel Manager Pro)是一款面向网络电视爱好者和运维管理人员的桌面级工具。它将频道数据管理与实时播放功能深度融合,打破了传统电视播放器只能"看"不能"管"的局限。用户既可以像操作数据库管理工具一样对频道分组、频道信息、播放地址进行精细化的增删改查操作,也可以一键切换到在线直播模式实时观看节目,还能打开本地媒体文件享受完整的播放器体验。系统采用多Tab页架构,每个功能模块独立运行互不干扰,数据全部从MySQL数据库动态获取,实现了真正的数据驱动。三套精心调校的主题样式让长时间使用也不觉疲劳,暗夜蓝沉稳大气、经典白清爽明朗、护眼绿温润养目,总有一款适合你的工作场景。


📐 项目结构

tv-manager/
├── tv_manager.py      # 核心程序 - 管理系统GUI + 本地播放 + 在线直播
├── tv.py              # 原始独立播放器(PyQt5 + VLC,可独立运行)
├── init.sql           # 数据库初始化脚本(DDL + 初始数据)
└── README.md          # 项目文档

🚀 快速开始

环境要求

组件
版本要求
用途
Python
3.7+
运行环境
MySQL
5.7+ / MariaDB 10.3+
数据存储
VLC 播放器
3.0+ (64位)
音视频解码
PyQt5
5.15+
GUI框架
pymysql
1.0+
数据库驱动
python-vlc
3.0+
VLC Python绑定

安装步骤

# 1. 安装Python依赖
pip install PyQt5 pymysql python-vlc

# 2. 初始化数据库(修改密码后执行)
mysql -u root -p < init.sql

# 3. 编辑 tv_manager.py 中的数据库连接配置
# DB_CONFIG -> host / port / user / password / database

# 4. 启动管理系统
python tv_manager.py

🎯 功能全景

Tab页
功能
说明
📁 频道分组
分组CRUD
创建/编辑/删除频道分类,支持排序
📺 频道管理
频道CRUD
按分组筛选、模糊搜索、收藏标记
🔗 URL管理
地址CRUD
多备用源、启用/禁用、优先级排序
🎬 本地播放
完整播放器
快进回退/倍速/字幕/音轨/截图/循环
📡 在线直播
直播观看
从数据库加载频道,多主题切换
👤 关于作者
项目信息
作者联系方式与技术栈

📖 核心代码详解

第一部分:数据库访问层(Database类)

数据库操作全部封装在 Database 类中,采用 pymysql 的 DictCursor 模式,查询结果直接以字典列表返回,上层无需关心SQL细节。

classDatabase:
"""MySQL数据库操作封装"""

def__init__(self, config):
        self.config = config

defget_connection(self):
return pymysql.connect(**self.config, cursorclass=pymysql.cursors.DictCursor)

defexecute(self, sql, params=None):
"""执行写操作(INSERT/UPDATE/DELETE)"""
        conn = self.get_connection()
try:
with conn.cursor() as cursor:
                cursor.execute(sql, params)
            conn.commit()
finally:
            conn.close()

deffetch_all(self, sql, params=None):
"""查询多条记录"""
        conn = self.get_connection()
try:
with conn.cursor() as cursor:
                cursor.execute(sql, params)
return cursor.fetchall()
finally:
            conn.close()

definsert(self, sql, params=None):
"""插入并返回自增ID"""
        conn = self.get_connection()
try:
with conn.cursor() as cursor:
                cursor.execute(sql, params)
                last_id = cursor.lastrowid
            conn.commit()
return last_id
finally:
            conn.close()

设计要点:

  • 每次操作独立获取连接、用完即关,避免长连接超时问题
  • 使用参数化查询(%s 占位符),防止SQL注入攻击
  • 写操作自动 commit,读操作无需事务
  • 级联删除依赖数据库外键 ON DELETE CASCADE,代码层无需手动清理子表

第二部分:本地播放器引擎

本地播放器基于 python-vlc 封装,延迟初始化策略确保在未安装 VLC 时不影响其他管理功能。

def_init_vlc_player(self):
"""延迟初始化VLC播放器"""
if self.vlc_player isnotNone:
returnTrue
try:
import vlc
        self.vlc_instance = vlc.Instance("--no-xlib", "--quiet")
        self.vlc_player = self.vlc_instance.media_player_new()
# 将VLC视频输出绑定到Qt的Frame控件
if sys.platform == "win32":
            self.vlc_player.set_hwnd(int(self.player_frame.winId()))
elif sys.platform == "darwin":
            self.vlc_player.set_nsobject(int(self.player_frame.winId()))
else:
            self.vlc_player.set_xwindow(int(self.player_frame.winId()))
        self.vlc_player.audio_set_volume(80)
# 500ms定时器驱动进度更新
        self.player_timer = QTimer()
        self.player_timer.timeout.connect(self._player_update_state)
        self.player_timer.start(500)
returnTrue
except Exception as e:
        QMessageBox.critical(self, "VLC初始化失败", f"...")
returnFalse

播放控制功能矩阵:

功能
实现方式
说明
快进/回退5s
set_time(current ± 5000)
毫秒级精确定位
倍速播放
set_rate(speed)
支持0.5x~3.0x
进度拖动
set_position(0~1.0)
配合sliderPressed/Released事件
音轨切换
audio_get_track_description()
 → audio_set_track()
循环切换所有音轨
字幕切换
video_get_spu_description()
 → video_set_spu()
支持内嵌字幕
截图
video_take_snapshot()
保存为PNG到screenshots目录
循环模式
列表循环/单曲循环/不循环
在Ended状态回调中判断

第三部分:在线直播与主题切换系统

在线直播Tab从数据库动态加载频道树,支持搜索过滤和多备用源自动切换。主题系统通过字典配置颜色方案,一键切换全部UI元素。

# 主题配置(颜色方案字典)
LIVE_THEMES = {
"暗夜蓝": {
"left_bg": "
#1a1a2e", "left_title_bg": "#16213e",
"tree_bg": "#1a1a2e", "tree_fg": "#e0e0e0",
"tree_hover": "#0f3460", "tree_sel": "#e94560",
"ctrl_bg": "#16213e", "accent": "#e94560",
"video_bg": "#000", "status_fg": "#888",
    },
"经典白": { ... },
"护眼绿": { ... },
}

def_live_apply_theme(self, theme_name):
"""将主题方案应用到所有UI控件"""
    t = LIVE_THEMES.get(theme_name)
    self.live_left.setStyleSheet(f"background:{t['left_bg']};")
    self.live_tree.setStyleSheet(f"""
        QTreeWidget {{ background:{t['tree_bg']}; color:{t['tree_fg']}; }}
        QTreeWidget::item:hover {{ background:{t['tree_hover']}; }}
        QTreeWidget::item:selected {{ background:{t['tree_sel']}; color:#fff; }}
    """
)
# ... 更多控件样式应用

备用源自动切换逻辑:

def_live_check_state(self):
"""每3秒检测播放状态,错误时自动切换备用源"""
    state = self.live_vlc_player.get_state()
if state == vlc.State.Error:
        self.live_error_count += 1
if self.live_error_count >= 2:
            self.live_current_url_idx += 1
if self.live_current_url_idx < len(self.live_current_urls):
# 还有备用源,自动切换
                url = self.live_current_urls[self.live_current_url_idx]
                media = self.live_vlc_instance.media_new(url)
                self.live_vlc_player.set_media(media)
                self.live_vlc_player.play()
else:
# 所有源失败
                self.live_state_label.setText("❌ 所有源均不可用")

🗄️ 数据库设计

ER关系图

┌─────────────────┐       ┌─────────────────┐       ┌─────────────────┐
│ channel_groups  │ 1:N   │    channels     │ 1:N   │  channel_urls   │
├─────────────────┤──────>├─────────────────┤──────>├─────────────────┤
│ id (PK)         │       │ id (PK)         │       │ id (PK)         │
│ name            │       │ group_id (FK)   │       │ channel_id (FK) │
│ sort_order      │       │ name            │       │ url             │
│ created_at      │       │ sort_order      │       │ sort_order      │
│ updated_at      │       │ is_favorite     │       │ is_active       │
└─────────────────┘       │ created_at      │       │ created_at      │
                          └─────────────────┘       └─────────────────┘

初始数据统计

分组名称
频道数
URL数
央视频道
8
8
韩国公共广播频道
3
3
国际公共广播频道
2
2
国内广播频道
1
1
合计1414

📚 知识点总结

1. PyQt5 GUI开发

  • QTabWidget 多页面架构:每个功能模块独立封装,互不干扰
  • QTableWidget 数据展示:配合 setSelectionBehavior(SelectRows) 实现整行选中
  • QTreeWidget 树形结构:用于频道分组展示,setData(Qt.UserRole) 存储业务数据
  • QSplitter 可拖拽分割:左右面板比例可调
  • QSlider 自定义样式:通过 groove/handle/sub-page 伪元素实现美观滑块
  • 信号槽机制:clicked.connect(handler) 实现事件驱动
  • QSS样式表:类CSS语法美化控件,支持伪状态(hover/selected)

2. MySQL + pymysql

  • 参数化查询防注入:使用 %s 占位符而非字符串拼接
  • 外键级联删除:ON DELETE CASCADE 自动清理关联数据
  • DictCursor 字典结果集:代码可读性远优于元组下标
  • 连接池思想:每次操作独立连接,生产环境可替换为 DBUtils 连接池

3. python-vlc 多媒体引擎

  • 跨平台窗口绑定:set_hwnd (Win) / set_nsobject (Mac) / set_xwindow (Linux)
  • 延迟初始化模式:仅在用户触发播放时才加载 VLC,避免启动阻塞
  • 状态机监控:定时器轮询 get_state() 驱动UI状态更新
  • 备用源切换:错误计数器触发自动 fallback

4. 软件设计模式

  • MVC分层:Database类(Model)、Tab界面(View)、事件处理(Controller)
  • 延迟加载:VLC播放器按需初始化,降低启动成本
  • 观察者模式:QTimer + 状态轮询实现异步状态监控
  • 策略模式:循环播放策略(列表循环/单曲循环/不循环)通过模式切换实现

🧪 测试步骤

功能测试清单

#
测试项
操作步骤
预期结果
1
数据库连接
点击「测试连接」
弹窗显示连接成功
2
新增分组
Tab1 → 新增分组 → 输入名称
表格刷新显示新分组
3
新增频道
Tab2 → 新增频道 → 选择分组
频道出现在对应分组下
4
新增URL
Tab3 → 新增URL → 填入地址
URL列表新增一行
5
级联删除
删除一个分组
其下频道和URL全部消失
6
模糊搜索
Tab2搜索框输入"CCTV"
仅显示包含CCTV的频道
7
本地播放
打开mp4文件 → 双击播放
视频正常播放,进度条走动
8
快进回退
播放中点击5s⏩
进度跳动约5秒
9
倍速播放
下拉选择2.0x
播放速度明显加快
10
音轨/字幕
点击音轨/字幕按钮
状态栏提示切换信息
11
截图
播放中点击📸
screenshots目录生成png
12
在线直播
Tab5点击频道
视频流开始播放
13
主题切换
下拉切换「护眼绿」
左侧面板颜色变为绿色调
14
备用源切换
播放一个失效URL
自动尝试下一个备用地址

拓展场景

  1. IPTV运营管理:可扩展为多用户权限系统,不同运营人员管理不同分组
  2. EPG电子节目单:增加 programs 表关联频道,展示节目时间表
  3. 自动巡检:定时任务批量检测所有URL可用性,自动标记失效源
  4. 收藏夹同步:将收藏数据同步到云端,多设备共享
  5. 录制功能:利用VLC的录制API实现定时录制功能
  6. M3U导入导出:支持标准M3U/M3U8格式的导入导出,兼容其他IPTV工具
  7. Web管理后台:基于Flask/Django开发Web版管理界面,远程维护
  8. Docker部署:将MySQL + 管理后台容器化,一键部署

👤 作者信息

项目
内容
作者
杨一凡
微信号
ysp2338084
公众号
Python学在坚持
文件下载地址
链接: https://pan.baidu.com/s/12UO-AUkG8CxzgGxTu8HHfA?pwd=xzjc 提取码: xzjc 复制这段内容后打开百度网盘手机App,操作更方便哦

⭐ 如果觉得有帮助,欢迎关注公众号获取更多Python实战项目 ⭐

© 2024-2026 Python学在坚持 All Rights Reserved

最新文章

随机文章