怎么改网站内容,教育培训类网站模板,深圳微信网站开发公司,网站建设哪些资质VideoAgentTrek-ScreenFilter项目实战#xff1a;构建一个完整的视频内容净化Web应用 你有没有遇到过这种情况#xff1f;从网上下载或者自己拍摄了一段视频#xff0c;里面有些画面不太合适#xff0c;比如突然出现的广告弹窗、不想展示的个人信息#xff0c;或者一些令…VideoAgentTrek-ScreenFilter项目实战构建一个完整的视频内容净化Web应用你有没有遇到过这种情况从网上下载或者自己拍摄了一段视频里面有些画面不太合适比如突然出现的广告弹窗、不想展示的个人信息或者一些令人不适的镜头。手动一帧帧去处理那工作量简直让人崩溃。现在借助AI的力量我们可以让这个过程变得自动化。今天要聊的就是如何把一个强大的视频内容净化模型——VideoAgentTrek-ScreenFilter包装成一个完整的、能直接上手的Web应用。这个应用能让你上传视频后台自动识别并处理掉那些不需要的内容最后把“干净”的视频下载回来。听起来是不是挺有用的无论是做内容创作、教育培训还是个人隐私保护都能派上用场。接下来我就带你从零开始一步步把这个想法变成现实。我们会从前端界面、后端服务到任务调度和数据库完整地走一遍。1. 项目整体规划我们要做个什么东西在动手写代码之前我们先得把蓝图画清楚。这个应用的核心目标很明确为用户提供一个网页能上传视频后台调用AI模型处理最后返回处理后的视频。为了实现这个目标我们需要几个关键部分协同工作用户看得见的界面前端一个简洁明了的网页有上传按钮、进度显示和结果下载区域。处理请求的大脑后端API接收前端发来的视频调用AI模型并管理整个处理流程。干重活的AI模型服务这是核心负责实际分析视频帧并执行内容净化操作。异步任务队列视频处理通常比较耗时不能让用户干等着需要后台悄悄处理。记忆存储数据库记录谁在什么时候处理了什么视频处理状态如何方便用户查看历史。整个系统的流程大致是这样的用户在前端上传视频 - 后端API接收并创建一个异步处理任务 - 任务队列将视频交给AI模型处理 - 处理完成后通知前端并提供下载链接。技术选型上我选择了这些组合主要是考虑它们既流行又好用前端Vue.js 3 Element Plus。Vue学起来快写起来也舒服Element Plus提供了大量现成的漂亮组件能快速搭出界面。后端FastAPI。Python系的现代框架写API特别简洁自动生成交互式文档调试起来很方便。AI模型服务VideoAgentTrek-ScreenFilter。这是我们项目的“主角”一个专门用于视频屏幕内容过滤的模型。任务队列Celery Redis。Celery是Python里处理异步任务的标准选择了搭配Redis作为消息中间件和结果存储非常成熟。数据库SQLite开发/ PostgreSQL生产。开发时用SQLite简单省事上线时换PostgreSQL更稳定可靠。文件存储本地磁盘开发或云存储如MinIO/S3生产环境。好了蓝图有了工具也选好了接下来我们就分头行动把这些部分一个个搭建起来。2. 搭建后端服务用FastAPI构建API大脑后端是整个应用的调度中心。我们先来创建它。首先建立项目结构并安装必要的依赖。创建一个新的项目目录比如video-filter-backend然后在里面初始化环境。# 创建项目目录并进入 mkdir video-filter-backend cd video-filter-backend # 创建虚拟环境推荐 python -m venv venv # Windows激活: venv\Scripts\activate # Mac/Linux激活: source venv/bin/activate # 安装核心依赖 pip install fastapi uvicorn celery redis pip install sqlalchemy pydantic python-multipart # 假设VideoAgentTrek-ScreenFilter模型包可通过pip安装 # pip install video-agent-trek-screenfilter接下来我们创建主要的应用文件main.py这里定义了核心的API接口。# main.py from fastapi import FastAPI, File, UploadFile, BackgroundTasks, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Optional import uuid import os from datetime import datetime from .tasks import process_video_task from .database import SessionLocal, VideoJob app FastAPI(title视频内容净化API, description基于VideoAgentTrek-ScreenFilter的Web服务) # 允许前端跨域请求 app.add_middleware( CORSMiddleware, allow_origins[http://localhost:8080], # 前端开发服务器地址 allow_credentialsTrue, allow_methods[*], allow_headers[*], ) # 定义上传文件存放的临时目录 UPLOAD_DIR uploads PROCESSED_DIR processed os.makedirs(UPLOAD_DIR, exist_okTrue) os.makedirs(PROCESSED_DIR, exist_okTrue) class VideoUploadResponse(BaseModel): job_id: str message: str app.post(/upload, response_modelVideoUploadResponse) async def upload_video( background_tasks: BackgroundTasks, file: UploadFile File(...) ): 接收用户上传的视频文件 # 1. 生成唯一任务ID和文件名 job_id str(uuid.uuid4()) file_extension os.path.splitext(file.filename)[1] safe_filename f{job_id}{file_extension} input_path os.path.join(UPLOAD_DIR, safe_filename) # 2. 保存上传的文件 try: contents await file.read() with open(input_path, wb) as f: f.write(contents) except Exception as e: raise HTTPException(status_code500, detailf文件保存失败: {str(e)}) # 3. 将任务信息存入数据库 db SessionLocal() db_job VideoJob( idjob_id, original_filenamefile.filename, stored_filenamesafe_filename, statuspending, created_atdatetime.utcnow() ) db.add(db_job) db.commit() db.refresh(db_job) db.close() # 4. 将耗时的视频处理任务放入后台队列 background_tasks.add_task(process_video_task, job_id, input_path) return VideoUploadResponse( job_idjob_id, message视频上传成功已开始后台处理。请使用job_id查询进度。 ) app.get(/status/{job_id}) async def get_job_status(job_id: str): 查询指定任务的处理状态 db SessionLocal() job db.query(VideoJob).filter(VideoJob.id job_id).first() db.close() if not job: raise HTTPException(status_code404, detail任务不存在) return { job_id: job.id, status: job.status, original_filename: job.original_filename, result_filename: job.result_filename, created_at: job.created_at, finished_at: job.finished_at, download_url: f/download/{job.result_filename} if job.result_filename else None } app.get(/download/{filename}) async def download_processed_video(filename: str): 下载处理完成的视频文件 file_path os.path.join(PROCESSED_DIR, filename) if not os.path.exists(file_path): raise HTTPException(status_code404, detail文件不存在) # 这里返回文件流实际前端会触发下载 from fastapi.responses import FileResponse return FileResponse(pathfile_path, filenamefilename)API有了我们需要一个地方来记录任务状态。这就用到了数据库。我们创建一个database.py文件来定义数据模型和连接。# database.py from sqlalchemy import create_engine, Column, String, DateTime, Text from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker import os # 使用SQLite数据库开发环境 SQLALCHEMY_DATABASE_URL sqlite:///./video_jobs.db engine create_engine( SQLALCHEMY_DATABASE_URL, connect_args{check_same_thread: False} ) SessionLocal sessionmaker(autocommitFalse, autoflushFalse, bindengine) Base declarative_base() class VideoJob(Base): __tablename__ video_jobs id Column(String, primary_keyTrue, indexTrue) original_filename Column(String) stored_filename Column(String) status Column(String) # pending, processing, completed, failed result_filename Column(String, nullableTrue) created_at Column(DateTime) finished_at Column(DateTime, nullableTrue) error_message Column(Text, nullableTrue) # 创建数据表 Base.metadata.create_all(bindengine)后端的基础骨架就搭好了。它提供了上传、查询和下载的接口并且能把任务状态记下来。接下来我们需要让这个大脑能指挥“双手”去干活。3. 集成AI模型与异步任务让Celery在后台默默处理视频处理是个体力活不能让用户一直等着网页转圈。所以我们引入Celery把重活放到后台去干。首先创建Celery的应用实例和任务定义。新建一个celery_app.py文件。# celery_app.py from celery import Celery import os # 使用Redis作为消息代理和结果后端 redis_url os.getenv(REDIS_URL, redis://localhost:6379/0) celery_app Celery( video_filter_worker, brokerredis_url, backendredis_url ) # 配置Celery celery_app.conf.update( task_serializerjson, accept_content[json], result_serializerjson, timezoneUTC, enable_utcTrue, )然后在tasks.py中定义具体的视频处理任务。这里就是调用VideoAgentTrek-ScreenFilter模型的地方。# tasks.py from .celery_app import celery_app from .database import SessionLocal, VideoJob from datetime import datetime import os import subprocess import uuid # 假设模型提供命令行接口或Python API # 这里用伪代码示意实际调用方式需参考模型文档 MODEL_PATH path/to/video-agent-trek-screenfilter # 或通过import调用 UPLOAD_DIR uploads PROCESSED_DIR processed celery_app.task(bindTrue, nameprocess_video) def process_video_task(self, job_id: str, input_video_path: str): Celery任务调用AI模型处理视频 db SessionLocal() try: job db.query(VideoJob).filter(VideoJob.id job_id).first() if not job: return {status: error, message: Job not found} # 更新状态为处理中 job.status processing db.commit() # 准备输出路径 output_filename fprocessed_{job_id}.mp4 output_path os.path.join(PROCESSED_DIR, output_filename) # 核心步骤调用VideoAgentTrek-ScreenFilter模型 # 注意以下命令为示例请根据模型实际使用方式调整 print(f开始处理任务 {job_id}: {input_video_path}) # 示例1假设模型提供命令行工具 # command fpython {MODEL_PATH} --input {input_video_path} --output {output_path} # result subprocess.run(command, shellTrue, capture_outputTrue, textTrue) # 示例2假设通过Python API调用 # from video_filter_model import VideoFilter # model VideoFilter() # model.process(input_video_path, output_path) # 此处为模拟成功处理 # 实际集成时请替换为真实的模型调用代码并做好错误处理 import time time.sleep(10) # 模拟处理耗时 # 假设处理成功生成一个模拟输出文件实际应保存模型真实输出 with open(output_path, w) as f: f.write(模拟处理后的视频内容) # 更新数据库任务完成 job.status completed job.result_filename output_filename job.finished_at datetime.utcnow() db.commit() print(f任务 {job_id} 处理完成: {output_path}) return {status: completed, output_path: output_path} except Exception as e: # 处理失败更新状态 if job: job.status failed job.error_message str(e) job.finished_at datetime.utcnow() db.commit() print(f任务 {job_id} 处理失败: {str(e)}) return {status: failed, error: str(e)} finally: db.close()现在我们需要修改main.py中的后台任务调用让它使用Celery任务。# 在main.py中修改或添加 # from .tasks import process_video_task # 这行可能已经存在 # 将其替换为从Celery导入任务 from .tasks import process_video_task # 现在这个是从celery_app导入的任务 # 在 /upload 接口中将 background_tasks.add_task 调用改为 # background_tasks.add_task(process_video_task, job_id, input_path) # 旧方式 # 新方式使用Celery的delay方法异步执行 process_video_task.delay(job_id, input_path) # 注意因为用了delayBackgroundTasks可能就不需要了可以移除相关参数和导入后端和任务队列都准备好了。要运行它们你需要启动几个服务Redis服务Celery依赖它。如果你用Docker可以docker run -p 6379:6379 redis。Celery Worker在项目根目录下运行celery -A app.celery_app worker --loglevelinfo。这个进程会监听任务并执行。FastAPI服务运行uvicorn app.main:app --reload --host 0.0.0.0 --port 8000。这样后端部分就活起来了可以接收请求并安排后台任务了。接下来我们给这个系统做一个好看又易用的“脸面”。4. 开发前端界面用Vue.js打造用户操作台用户不会直接调用API他们需要一个网页。我们用Vue 3和Element Plus来快速构建。使用Vite创建一个新的Vue项目这样更现代、更快。# 创建Vue项目 npm create vuelatest video-filter-frontend # 按照提示选择项目配置记得加入Router和Pinia状态管理 cd video-filter-frontend npm install # 安装Element Plus和Axios用于HTTP请求 npm install element-plus axios npm install --save-dev sass项目创建好后我们修改主要的页面组件src/views/HomeView.vue或者你创建的新页面。template div classhome-container el-card classupload-card template #header div classcard-header span视频内容净化工具/span /div /template !-- 上传区域 -- el-upload classupload-demo drag action# !-- 因为我们要自定义上传所以这里覆盖 -- :auto-uploadfalse :on-changehandleFileChange :show-file-listfalse acceptvideo/* el-icon classel-icon--uploadupload-filled //el-icon div classel-upload__text 将视频文件拖到此处或 em点击选择/em /div template #tip div classel-upload__tip 支持 mp4, avi, mov 等常见视频格式文件大小建议不超过500MB。 /div /template /el-upload !-- 文件信息和上传按钮 -- div v-ifselectedFile classfile-info el-text已选择文件: {{ selectedFile.name }} ({{ formatFileSize(selectedFile.size) }})/el-text el-button typeprimary :loadinguploading clicksubmitUpload 开始处理 /el-button /div !-- 任务状态展示 -- div v-ifcurrentJobId classjob-status el-divider / h3处理任务状态/h3 el-text任务ID: {{ currentJobId }}/el-text br/ el-text状态: el-tag :typestatusTagType{{ jobStatus || 等待中... }}/el-tag /el-text div v-ifjobStatus processing classprogress-area el-progress :percentageprogressPercentage :indeterminatetrue / el-text typeinfo视频正在后台处理中请稍候.../el-text /div !-- 处理完成后的下载区域 -- div v-ifjobStatus completed classresult-area el-result iconsuccess title处理完成 template #extra el-button typeprimary clickdownloadResult 下载净化后的视频 /el-button /template /el-result /div div v-ifjobStatus failed classerror-area el-result iconerror title处理失败 template #extra el-text typedanger{{ errorMessage }}/el-text br/ el-button clickresetUpload重新上传/el-button /template /el-result /div /div /el-card !-- 历史记录表格 (可选) -- el-card v-iffalse classhistory-card !-- 先隐藏后续可扩展 -- template #header div classcard-header span处理历史/span /div /template 历史记录功能待开发... /el-card /div /template script setup import { ref, onUnmounted } from vue import { UploadFilled } from element-plus/icons-vue import axios from axios const API_BASE_URL http://localhost:8000 // 后端API地址 const selectedFile ref(null) const uploading ref(false) const currentJobId ref(null) const jobStatus ref() const progressPercentage ref(0) const errorMessage ref() let statusPollingInterval null const handleFileChange (file) { selectedFile.value file.raw } const formatFileSize (bytes) { if (bytes 0) return 0 B const k 1024 const sizes [B, KB, MB, GB] const i Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) sizes[i] } const submitUpload async () { if (!selectedFile.value) { ElMessage.warning(请先选择视频文件) return } uploading.value true const formData new FormData() formData.append(file, selectedFile.value) try { const response await axios.post(${API_BASE_URL}/upload, formData, { headers: { Content-Type: multipart/form-data } }) currentJobId.value response.data.job_id ElMessage.success(response.data.message) // 开始轮询查询任务状态 startStatusPolling() } catch (error) { ElMessage.error(上传失败: (error.response?.data?.detail || error.message)) } finally { uploading.value false } } const startStatusPolling () { if (statusPollingInterval) clearInterval(statusPollingInterval) statusPollingInterval setInterval(async () { if (!currentJobId.value) return try { const response await axios.get(${API_BASE_URL}/status/${currentJobId.value}) const data response.data jobStatus.value data.status if (data.status completed) { clearInterval(statusPollingInterval) ElMessage.success(视频处理完成) } else if (data.status failed) { clearInterval(statusPollingInterval) errorMessage.value data.error_message || 处理过程发生错误 ElMessage.error(处理失败) } // pending 和 processing 状态继续轮询 } catch (error) { console.error(查询状态失败:, error) } }, 2000) // 每2秒查询一次 } const statusTagType computed(() { switch(jobStatus.value) { case pending: return info case processing: return case completed: return success case failed: return danger default: return info } }) const downloadResult () { if (currentJobId.value) { // 触发浏览器下载 window.open(${API_BASE_URL}/download/processed_${currentJobId.value}.mp4, _blank) } } const resetUpload () { selectedFile.value null currentJobId.value null jobStatus.value if (statusPollingInterval) { clearInterval(statusPollingInterval) statusPollingInterval null } } // 组件卸载时清除定时器 onUnmounted(() { if (statusPollingInterval) clearInterval(statusPollingInterval) }) /script style scoped .home-container { max-width: 800px; margin: 40px auto; padding: 20px; } .upload-card, .history-card { margin-bottom: 24px; } .card-header { display: flex; justify-content: space-between; align-items: center; } .file-info { margin-top: 20px; display: flex; justify-content: space-between; align-items: center; } .job-status { margin-top: 20px; } .progress-area, .result-area, .error-area { margin-top: 20px; } /style最后在src/main.js或src/main.ts中全局引入Element Plus。// src/main.js import { createApp } from vue import App from ./App.vue import router from ./router // 引入Element Plus import ElementPlus from element-plus import element-plus/dist/index.css const app createApp(App) app.use(router) app.use(ElementPlus) app.mount(#app)现在运行npm run dev打开浏览器访问http://localhost:5173你应该能看到一个简洁的上传界面了。选择视频文件点击上传就能看到任务状态在动态更新。前端和后端终于连通了5. 项目部署与优化让应用稳定跑起来开发环境跑通了但要真正给别人用我们还得考虑部署和优化。这里提供几个关键方向。5.1 使用Docker容器化Docker能确保环境一致部署方便。我们为后端和前端分别创建Dockerfile。后端Dockerfile (backend/Dockerfile):FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 安装VideoAgentTrek-ScreenFilter模型依赖根据实际情况调整 # RUN pip install video-agent-trek-screenfilter CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000]前端Dockerfile (frontend/Dockerfile):FROM node:18-alpine as build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine as production-stage COPY --frombuild-stage /app/dist /usr/share/nginx/html EXPOSE 80 CMD [nginx, -g, daemon off;]然后用一个docker-compose.yml文件把整个系统后端、前端、Redis、数据库串起来。version: 3.8 services: redis: image: redis:alpine ports: - 6379:6379 postgres: # 生产环境用PostgreSQL image: postgres:15 environment: POSTGRES_DB: video_filter POSTGRES_USER: admin POSTGRES_PASSWORD: your_secure_password volumes: - postgres_data:/var/lib/postgresql/data ports: - 5432:5432 backend: build: ./video-filter-backend ports: - 8000:8000 environment: - DATABASE_URLpostgresql://admin:your_secure_passwordpostgres/video_filter - REDIS_URLredis://redis:6379/0 depends_on: - redis - postgres volumes: - ./uploads:/app/uploads # 持久化上传文件 - ./processed:/app/processed celery-worker: build: ./video-filter-backend command: celery -A app.celery_app worker --loglevelinfo environment: - DATABASE_URLpostgresql://admin:your_secure_passwordpostgres/video_filter - REDIS_URLredis://redis:6379/0 depends_on: - backend - redis volumes: - ./uploads:/app/uploads - ./processed:/app/processed frontend: build: ./video-filter-frontend ports: - 8080:80 depends_on: - backend volumes: postgres_data:运行docker-compose up -d所有服务就会在后台启动一个完整的应用就部署好了。5.2 生产环境优化建议文件存储别把视频文件直接存在服务器磁盘。换成云存储服务如AWS S3、阿里云OSS、或自建的MinIO更可靠也方便扩展。安全加固API接口加上认证如JWT令牌。对上传文件做严格检查类型、大小、病毒扫描。设置合理的请求频率限制。性能与监控用Nginx做反向代理处理静态文件和负载均衡。为Celery设置多个Worker进程并行处理任务。接入监控如PrometheusGrafana观察API响应时间、任务队列长度、系统资源使用情况。模型优化VideoAgentTrek-ScreenFilter模型本身可能支持GPU加速。确保部署环境有合适的CUDA驱动并在调用模型时启用GPU这能极大提升处理速度。6. 写在最后走完这一趟一个具备完整前后端的视频内容净化Web应用就从想法变成了现实。我们用了Vue.js让用户操作简单直观用FastAPI搭建了高效的后台用Celery保证了耗时任务不阻塞用户再用数据库把一切记录在案。实际开发中你可能会遇到更多细节问题比如模型如何精确集成、大文件上传怎么优化、处理进度如何更细腻地展示等等。但这个项目骨架已经搭好了剩下的就是根据具体需求往上添砖加瓦。这种“前端展示 后端调度 AI模型服务 异步任务”的模式非常通用。不只是视频净化很多AI应用比如图片风格迁移、语音识别、文档分析都可以套用这个架构。希望这个实战项目能给你带来启发当你下次有好的AI想法时知道如何一步步把它变成一个可用的产品。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。