当前位置: 首页 > news >正文

极简短视频查看、删除应用

本地短视频服务器

背景:我的NAS中存放了很多短视频,多到很多没看过,于是写了这个程序来随机查看并删除短视频

运行:

安装依赖后运行main.py

直接使用docker:

docker pull realwang/short_video

docker run -d -p 3000:3000 -v /path/to/your/video:/app/video realwang/short_video

功能

  • 扫描本地视频和图片,并在网页上显示
  • 在网页上 点赞和删除文件
  • 上下滑动来切换文件
  • 媒体文件放在video目录下
  • 本地数据库

代码由4个文件组成

1.数据库操作
# database.pyimport sqlite3def init_db():conn = sqlite3.connect('media.db')c = conn.cursor()c.execute('''CREATE TABLE IF NOT EXISTS media(id INTEGER PRIMARY KEY, name TEXT, path TEXT, views INTEGER DEFAULT 0, likes INTEGER DEFAULT 0)''')conn.commit()conn.close()def add_media(name, path):try:conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("INSERT INTO media (name, path) VALUES (?, ?)", (name, path))conn.commit()conn.close()return Trueexcept sqlite3.IntegrityError:# 处理重复键错误等数据库约束错误return Falseexcept Exception as e:print(f"Error inserting {name} into database: {str(e)}")return Falsedef update_views(media_id):conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("UPDATE media SET views = views + 1 WHERE id = ?", (media_id,))conn.commit()conn.close()def update_likes(media_id):conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("UPDATE media SET likes = likes + 1 WHERE id = ?", (media_id,))conn.commit()conn.close()def delete_media(media_id):conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("DELETE FROM media WHERE id = ?", (media_id,))conn.commit()conn.close()def get_random_media():conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT id, name, path FROM media ORDER BY RANDOM() LIMIT 1")media = c.fetchone()conn.close()return media
2.文件扫描
#scanner.py
import os
import time
import sqlite3
from database import init_db, add_mediadef scan_directory(directory='video'):init_db()print(f"扫描目录: {directory}")for root, dirs, files in os.walk(directory):for file in files:if file.endswith(('.mp4', '.jpg', '.png', '.gif')):path = os.path.join(root, file)print(f"发现文件: {file} 路径: {path}")try:result = add_media(file, path)#print(f"add_media 返回: {result}")  # Debug: Print the return valueif result:print(f"插入 {file} 到数据库")else:print(f"插入 {file} 到数据库失败")except Exception as e:print(f"由于异常无法插入 {file} 到数据库: {str(e)}")def incremental_scan(directory='video'):scanned_files = set()conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT path FROM media")for row in c.fetchall():scanned_files.add(row[0])conn.close()print("开始增量扫描...")for root, dirs, files in os.walk(directory):for file in files:if file.endswith(('.mp4', '.jpg', '.png', '.gif')):path = os.path.join(root, file)if path not in scanned_files:print(f"发现新文件: {file} 路径: {path}")try:result = add_media(file, path)print(f"add_media 返回: {result}")  # Debug: Print the return valueif result:print(f"插入 {file} 到数据库")else:print(f"插入 {file} 到数据库失败")except Exception as e:print(f"由于异常无法插入 {file} 到数据库: {str(e)}")else:print(f"跳过已存在文件: {file}")if __name__ == '__main__':init_db()while True:incremental_scan()time.sleep(3600)  # 每小时扫描一次
3.web服务
#app.pyfrom flask import Flask, render_template, request, send_file, jsonify, send_from_directory
import os
import sqlite3
import random  # 导入 random 模块
from database import init_db, update_views, update_likes, delete_media, get_random_mediaapp = Flask(__name__)def is_video_file(path):return path.lower().endswith('.mp4')def is_image_file(path):return path.lower().endswith('.jpg') or path.lower().endswith('.jpeg') or path.lower().endswith('.png')def get_random_media():conn = sqlite3.connect('media.db')c = conn.cursor()rand_num = random.random()  # Generate a random number between 0 and 1if rand_num < 0.9:c.execute("SELECT id, name, path FROM media WHERE path LIKE '%.mp4' ORDER BY RANDOM() LIMIT 1;")else:c.execute("SELECT id, name, path FROM media WHERE path LIKE '%.jpg' OR path LIKE '%.jpeg' OR path LIKE '%.png' ORDER BY RANDOM() LIMIT 1;")media = c.fetchone()conn.close()return media@app.route('/')
def index():media = get_random_media()if media:media_id, name, path = mediaupdate_views(media_id)conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT likes FROM media WHERE id = ?", (media_id,))likes = c.fetchone()[0]conn.close()return render_template('index.html', media_id=media_id, name=name, path=path, likes=likes,is_video=is_video_file(path), is_image=is_image_file(path))return "No media found"@app.route('/media/<path:filename>')
def media(filename):return send_from_directory(directory=os.path.dirname(filename), path=os.path.basename(filename))@app.route('/like/<int:media_id>', methods=['POST'])
def like(media_id):update_likes(media_id)conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT likes FROM media WHERE id = ?", (media_id,))likes = c.fetchone()[0]conn.close()return jsonify(success=True, likes=likes)@app.route('/delete/<int:media_id>', methods=['POST'])
def delete(media_id):conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT path FROM media WHERE id = ?", (media_id,))path = c.fetchone()[0]conn.close()if os.path.exists(path):os.remove(path)delete_media(media_id)return jsonify(success=True)@app.route('/download/<int:media_id>')
def download(media_id):conn = sqlite3.connect('media.db')c = conn.cursor()c.execute("SELECT path FROM media WHERE id = ?", (media_id,))path = c.fetchone()[0]conn.close()return send_file(path, as_attachment=True)if __name__ == '__main__':init_db()  # 确保数据库和表被初始化app.run(host='0.0.0.0', port=3000, debug=True)
4.启动器
import os
import threading
import time# 定义运行scanner.py的函数
def run_scanner():# 清空并创建scanner.log文件with open('log/scanner.log', 'wb') as f:passos.system('python scanner.py > log/scanner.log 2>&1')# 定义运行app.py的函数
def run_app():# 清空并创建app.log文件with open('log/app.log', 'wb') as f:passos.system('python app.py > log/app.log 2>&1')if __name__ == '__main__':# 创建log子目录os.makedirs('log', exist_ok=True)# 创建并启动线程运行scanner.pyscanner_thread = threading.Thread(target=run_scanner)scanner_thread.start()# 等待3秒钟time.sleep(3)# 创建并启动线程运行app.pyapp_thread = threading.Thread(target=run_app)app_thread.start()

相关文章:

极简短视频查看、删除应用

本地短视频服务器 背景&#xff1a;我的NAS中存放了很多短视频&#xff0c;多到很多没看过&#xff0c;于是写了这个程序来随机查看并删除短视频 运行&#xff1a; 安装依赖后运行main.py 直接使用docker&#xff1a; docker pull realwang/short_video docker run -d -p 3000:…...

【秋招刷题打卡】Day01-自定义排序

Day01-自定排序 前言 给大家推荐一下咱们的 陪伴打卡小屋 知识星球啦&#xff0c;详细介绍 >笔试刷题陪伴小屋-打卡赢价值丰厚奖励 < ⏰小屋将在每日上午发放打卡题目&#xff0c;包括&#xff1a; 一道该算法的模版题 (主要以力扣&#xff0c;牛客&#xff0c;acwin…...

API低代码平台介绍6-数据库记录删除功能

数据库记录删除功能 在前续文章中我们介绍了如何插入和修改数据库记录&#xff0c;本篇文章会沿用之前的测试数据&#xff0c;介绍如何使用ADI平台定义一个删除目标数据库记录的接口&#xff0c;包括 单主键单表删除、复合主键单表删除、多表删除&#xff08;整合前两者&#x…...

计算机基础之:硬件系统的性能评估标准

服务器时钟的性能通常涉及多个方面&#xff0c;主要包括准确性、稳定性、以及对系统性能的影响。以下是一些关键指标和衡量方法&#xff1a; 准确性&#xff1a; 时间偏移&#xff1a;测量服务器时钟与一个可靠时间源&#xff08;如GPS时间、原子钟或NTP服务器&#xff09;之间…...

高互动UI设计揭秘:动画效果如何提升用户体验

动画&#xff0c;由于其酷的视觉冲击&#xff0c;往往会产生极好的用户体验。UI设计中的动态效果可以使用户界面看起来更酷&#xff0c;特别是界面的功能动画&#xff0c;是UX设计的重要组成部分&#xff0c;不容忽视。为什么UI设计的动态效果如此重要&#xff1f;接下来&#…...

探索Java异常处理的奥秘:源码解析与高级实践

1. 引言 在Java编程的广阔天地中,异常处理是确保程序健壮性、稳定性和可维护性的重要基石。对于Java工程师而言,深入理解Java异常处理的机制,并能够在实践中灵活运用,是迈向卓越的重要一步。 2. 基本概念 在Java中,异常(Exception)是程序执行期间出现的不正常或错误情况…...

深入了解python函数与函数内存使用

函数的定义 函数作为代码复用的基本单元&#xff0c;可以帮助我们组织代码、减少重复、提高可读性和可维护性。 在 Python 中&#xff0c;函数本质上是对象&#xff0c;可以赋值给变量、存储在数据结构中、作为参数传递和返回。 函数与内存 函数的加载和调用过程中&#xff…...

Java面试----MySQL面试题

1.索引有哪些优缺点&#xff1f; MySQL索引作为一种提升数据库查询效率的重要机制&#xff0c;具有以下主要优点和缺点&#xff1a; 优点&#xff1a; 提高查询速度&#xff1a; 索引能够显著加速数据的检索过程&#xff0c;类似于书籍的目录&#xff0c;让数据库引擎能够快速…...

python从入门到精通2:缩进

在Python中&#xff0c;缩进&#xff08;Indentation&#xff09;是一个非常重要的语法元素&#xff0c;它用于表示代码块的结构。与其他许多编程语言使用大括号 {} 来定义代码块不同&#xff0c;Python使用缩进来确定代码块的开始和结束。这种简洁的语法使得Python代码更加清晰…...

了解CDN:提升网络性能和安全性的利器

在当今的数字时代&#xff0c;网站性能和安全性是每一个网站管理员必须关注的核心问题。内容分发网络&#xff08;CDN&#xff0c;Content Delivery Network&#xff09;作为解决这一问题的重要工具&#xff0c;逐渐成为主流。本文将详细介绍CDN的定义、作用及其工作原理&#…...

ChatGPT的工作原理

ChatGPT的工作原理可以详细分为以下几个步骤&#xff0c;下面将结合相关信息进行清晰、详细的介绍&#xff1a; 数据收集&#xff1a; ChatGPT首先会从大量的文本数据中收集信息&#xff0c;这些数据可能包括网页、新闻、书籍等多样化的来源。它还会特别关注和分析网络上的热点…...

基于DPU的云原生裸金属服务快速部署及存储解决方案

1. 背景介绍 1.1. 业务背景 在云原生技术迅速发展的当下&#xff0c;容器技术因其轻量级、可移植性和快速部署的特性而成为应用部署的主流选择&#xff0c;但裸金属服务器依然有其独特的价值和应用场景&#xff0c;是云原生架构中不可或缺的一部分。 裸金属服务器是一种高级…...

论文学习_Large Language Models Based Fuzzing Techniques: A Survey

论文名称发表时间发表期刊期刊等级研究单位Large Language Models Based Fuzzing Techniques: A Survey 2024年arXiv-悉尼大学 0.摘要 研究背景在软件发挥举足轻重作用的现代社会,软件安全和漏洞分析对软件开发至关重要,模糊测试作为一种高效的软件测试方法,并广泛应用于各个…...

响应式德米拉数字内容交易系统素材下载站模板

★模板说明★ 该数字交易系统设计非常完美&#xff0c;两种响应式模式&#xff0c;可打开边栏模式和盒子模式&#xff1b;八种网站颜色&#xff0c;四种风格颜色可供用户自行选择&#xff0c;还可在网站选背景图片&#xff1b;完美的分成系统、充值功能、个人中心等等都以html…...

数据库开发-MySQL

前言 首先来了解一下什么是数据库。 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 像我们日常访问的电商网站京东&#xff0c;企业内部的管理系统OA、ERP、CRM这类的系统&#xff0c;以及大家每天都会刷的头条、抖音类的app…...

香港大带宽服务器高性能配置选择灵活

香港大带宽服务器是指在香港数据中心托管的&#xff0c;配备了高速网络连接的服务器。这些服务器通常用于需要大量数据传输和快速响应时间的应用&#xff0c;如视频流媒体、在线游戏、远程工作和大规模数据处理任务。具体分析如下&#xff0c;rak部落为您整理发布。 1. **内存配…...

Oracle中生僻汉字的解决办法

在Oracle数据库中处理生僻汉字时&#xff0c;主要面临的问题是某些字符集可能无法完全支持所有的汉字&#xff0c;特别是生僻字。以下是一些解决Oracle中生僻汉字问题的办法&#xff1a; 检查当前字符集&#xff1a; 使用SELECT USERENV(language) FROM dual;命令来查看当前数…...

在Kotlin中,`field`关键字是一个特殊的标识符,用于在属性的自定义getter和setter中访问backing field(存储属性值的实际字段)

在Kotlin中&#xff0c;field关键字是一个特殊的标识符&#xff0c;用于在属性的自定义getter和setter中访问backing field&#xff08;存储属性值的实际字段&#xff09;。Kotlin属性默认提供getter和setter方法&#xff0c;但当你需要自定义它们的行为时&#xff0c;可以使用…...

如何在 MySQL 中创建和使用事务?

目录 1. 环境准备 2. 创建事务 3. 事务执行 4. 事务撤消 5. 总结 事务是数据库区别于文件系统的重要特征之一&#xff0c;当我们有了事务就会让数据库始终保持一致&#xff0c;同时我们还能通过事务机制恢复到某个时间点&#xff0c;这样可以保证已提交到数据库的修改不会…...

Python数据分析-对驾驶安全数据进行了预测

一、研究背景和意义 随着汽车保有量的不断增加&#xff0c;交通事故已成为全球范围内的重大公共安全问题。每年因交通事故造成的人员伤亡和财产损失给社会带来了巨大的负担。为了提高驾驶安全&#xff0c;减少交通事故的发生&#xff0c;许多研究致力于探索影响驾驶安全的因素…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...