flask 实现简易视频播放网站案例
本视频主要实现两个目的,上传视频、播放视频。
使用技术: flask、flask-sqlalchemy、layui
视频地址: https://www.bilibili.com/video/BV1QV411N7qy/
搭建项目
直接新建一个 flask 项目,然后下载 layui 的静态文件丢到 static 目录下。然后再编写视频信息展示的首页。当然在此之前需要先做好数据库的模型创建,否则视频信息展示的时候会出问题。
创建项目
直接用 pycharm 创建一个 flask 项目,创建成功后目录如下
X:\flask-video>tree /f
X:.
│ app.py
│
├─static
└─templates
然后访问 https://layui.dev/ ,点击直接下载之后就能得到 layui 的静态文件,将其复制到 static 目录下,完成之后的目录结构如下
X:\flask-video>tree /f
X:.
│ app.py
│
├─static
│ │ layui.js
│ │
│ ├─css
│ │ layui.css
│ │
│ └─font
│ iconfont.eot
│ iconfont.svg
│ iconfont.ttf
│ iconfont.woff
│ iconfont.woff2
│
└─templates
配置插件
1、安装插件
| pip install flask-sqlalchemy |
2、添加配置文件
| |
| app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///flask-video.db" |
| |
| app.config["UPLOAD_FOLDER"] = 'static/upload/video' |
3、创建实例对象
| from flask_sqlalchemy import SQLAlchemy |
| |
| |
| db = SQLAlchemy() |
| |
| db.init_app(app) |
4、创建视频数据模型
| import sqlalchemy as sa |
| |
| class MovieORM(db.Model): |
| __tablename__ = 'movie' |
| id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) |
| name = sa.Column(sa.String(255), nullable=False) |
| url = sa.Column(sa.String(255), nullable=False) |
| create_at = sa.Column(sa.DateTime, default=datetime.now) |
5、生成测试数据
| @app.cli.command() |
| def create(): |
| db.drop_all() |
| db.create_all() |
| |
| mv = MovieORM() |
| mv.name = '默认演示电影' |
| mv.url = '/static/upload/video/7e245fc2483742414604ce7e67c13111.mp4' |
| db.session.add(mv) |
| db.session.commit() |
视频观看
1、后端返回数据
| @app.route('/') |
| def hello_world(): |
| q = db.select(MovieORM) |
| movie_list = db.session.execute(q).scalars() |
| return render_template('index.html', movie_list=movie_list) |
2、前端渲染基础页面
| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>正心的视频播放网站</title> |
| <link rel="stylesheet" href="/static/css/layui.css"> |
| <style> |
| .title { |
| margin-top: 100px; |
| text-align: center; |
| font-size: 52px; |
| } |
| </style> |
| </head> |
| <body> |
| |
| <h2 class="title">正心の专属视频播放网站</h2> |
| |
| <div class="layui-container"> |
| |
| </div> |
| |
| <script src="/static/layui.js"></script> |
| </body> |
| </html> |
3、渲染搜索表单
| <div class="layui-form" style="width: 50%;margin: 20px auto;"> |
| <div class="layui-form-item"> |
| <div class="layui-input-group"> |
| <input type="text" placeholder="请输入电影名" class="layui-input"> |
| <div class="layui-input-suffix"> |
| <button type="submit" class="layui-btn" lay-submit lay-filter="demo1">点击搜索</button> |
| <a href="/upload_movie" class="layui-btn layui-btn-primary layui-border-green">我要上传</a> |
| </div> |
| </div> |
| </div> |
| </div> |
4、渲染视频数据
| <table class="layui-table" style="width: 50%;margin: 0 auto"> |
| <colgroup> |
| <col width="120"> |
| <col width="180"> |
| <col> |
| </colgroup> |
| <thead> |
| <tr> |
| <th>电影名</th> |
| <th>上传时间</th> |
| <th>观看</th> |
| </tr> |
| </thead> |
| <tbody> |
| {% for movie in movie_list %} |
| <tr> |
| <td>{{ movie.name }}</td> |
| <td>{{ movie.create_at.strftime('%Y-%m-%d %H:%M:%S') }}</td> |
| <td><a href="{{ movie.url }}" class="layui-btn layui-btn-sm">点击观看</a> |
| <a href="/video_view?url={{ movie.url }}" class="layui-btn layui-btn-sm">点击观看2</a> |
| </td> |
| </tr> |
| {% endfor %} |
| </tbody> |
| </table> |
5、新窗口播放视频
先处理后端接口请求
| @app.route('/video_view') |
| def video_view(): |
| url = request.args.get('url') |
| return render_template('video_view.html', url=url) |
然后再在前端进行渲染
| |
| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>上传视频 | 正心的视频播放网站</title> |
| <link rel="stylesheet" href="/static/css/layui.css"> |
| <style> |
| .title { |
| margin-top: 100px; |
| text-align: center; |
| font-size: 52px; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="layui-container"> |
| <h2 class="title">视频观看</h2> |
| <video style="max-width: 100%;" controls="controls" poster="{{ url }}"> |
| <source src="{{ url }}" type="video/mp4"/> |
| </video> |
| </div> |
| <script src="/static/layui.js"></script> |
| </body> |
| </html> |
视频上传
1、后端返回视频上传页面
| @app.get('/upload_movie') |
| def upload_movie(): |
| return render_template('video_upload.html') |
2、前端进行视频上传
| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>上传视频 | 正心的视频播放网站</title> |
| <link rel="stylesheet" href="/static/css/layui.css"> |
| <style> |
| .title { |
| margin-top: 100px; |
| text-align: center; |
| font-size: 52px; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="layui-container"> |
| <h2 class="title">上传视频文件</h2> |
| <div style="width: 50%;margin: 0 auto"> |
| <button type="button" class="layui-btn demo-class-accept" lay-options="{accept: 'video'}"> |
| <i class="layui-icon layui-icon-upload"></i> |
| 上传视频 |
| </button> |
| </div> |
| |
| </div> |
| <script src="/static/layui.js"></script> |
| <script> |
| layui.use(function () { |
| var upload = layui.upload; |
| var layer = layui.layer; |
| |
| upload.render({ |
| elem: '.demo-class-accept', |
| url: '/video_upload', |
| accept: 'file', |
| done: function (res) { |
| layer.msg('上传成功'); |
| console.log(res); |
| } |
| }); |
| }); |
| </script> |
| </body> |
| </html> |
3、后端接受并保存视频
| @app.post('/video_upload') |
| def upload_movie2(): |
| file = request.files['file'] |
| if file: |
| filename = file.filename |
| content = file.read() |
| name = hashlib.md5(content).hexdigest() |
| suffix = os.path.splitext(filename)[-1] |
| new_filename = name + suffix |
| new_path = os.path.join(app.config['UPLOAD_FOLDER'], new_filename) |
| open(new_path, mode='wb').write(content) |
| |
| mv = MovieORM() |
| mv.url = '/' + new_path |
| mv.name = filename |
| db.session.add(mv) |
| db.session.commit() |
| |
| return { |
| 'code': 0, 'msg': '上传视频成功' |
| } |
项目后续
项目仅仅是一个小案例,不足的地方还有非常多,可以优化的地方也有很多
视频信息没有实现删除功能。在实现删除功能的时候,不仅是需要删除数据库中的数据,还需要删除视频文件。
视频信息没有完成修改的功能。
上传的时候没有做限制,播放的时候也没有分片加载与加密。
有些知识点在往期的文章中有写过,在这里就不赘述了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了