一、言映AI视频生成项目页面展示

1.1言映视频展示首页

2.1言映视频生成页面展示

2.3历史视频页面展示

二、项目介绍

本项目包括三个页面视频首页展示,视频生成页面,历史视频页面。实现的功能有,文字生成视频,图片生成视频,以及基于文字生成视频的首尾帧生成视频,本项目核心功能实现使用智谱清言的cogrevidio3模型实现视频功能,所以在完成本项目之前需要在智谱清言官网申请api密钥。

三、项目实现的基本流程

  1. 视频任务创建:用户填写任务表单,包含视频标题(必填)、文本脚本或主题描述(支持富文本编辑器),选择视频模板(支持分类筛选),并设置视频时长、分辨率、语言、语音性别等参数,还可上传参考素材(图片、音频)。提交后生成唯一任务 ID,任务状态设为 “待处理” 并加入异步任务队列。

  2. CogreVideo3集成:后端通过 API 调用 智谱清言 平台工作流,传递任务参数。大模型自动完成脚本优化与分镜生成、AI 语音合成(TTS)、关键帧图像生成、视频片段合成与剪辑、后期处理(添加字幕、背景音乐、转场效果)等步骤,工作流状态实时同步至系统数据库。

  3. 任务进度监控:用户在 “我的任务” 页面可查看所有任务状态(待处理→处理中→生成成功→可预览 / 下载,失败时显示失败原因),支持手动刷新、取消任务(仅限 “处理中” 前)、重新生成(失败任务可修改后重试),进度通过 WebSocket 实时推送。

  4. 视频预览与下载:视频生成成功后,提供 H5 视频播放器在线预览,支持 MP4(高清 / 标清)、MOV、GIF(可选片段导出)等多种格式下载,下载前提示文件大小与网络建议,且支持断点续传(通过对象存储签名 URL 实现)。

四、项目使用的技术栈

系统采用前后端分离架构,各层级技术选型精心搭配,保障系统稳定高效运行:

层级 技术选型 作用
前端 Vue.js + Element Plus + WebSocket 为用户提供流畅、直观的操作界面,通过 WebSocket 实现任务进度实时推送,提升用户体验
后端 Python + Django + Django REST Framework 构建稳定、高效的后端服务,处理业务逻辑、用户请求等
数据库 MySQL 8.0(元数据) + Redis(缓存 / 会话) MySQL 存储系统元数据,Redis 用于缓存数据和管理用户会话,提高数据访问效率
存储 对象存储(如 AWS S3 / 阿里云 OSS) 安全、可靠地存储大量视频文件,支持视频的预览与下载
异步任务 Celery + RabbitMQ/Redis 负责处理视频生成等耗时任务,避免阻塞主线程,提升系统并发处理能力
AI 引擎 Cogrevideo3(调用文生图、TTS、视频合成等模型) 集成多种 AI 能力,实现从文本到视频的全流程自动化生成
实时通信 WebSocket 实时推送任务进度,让用户及时了解视频生成状态

五、项目实现

5.1后端实现

后端使用Django框架开发增加项目的稳定性。

实现流程:

①首先在pychram当中创建一个Django项目。

②创建一个Videoyanying的应用。

③在主项目文件夹下urls.py文件当中注册应用的域名。

④在videoyanying项目的视图层文件当中创建视频生成类。

⑤在创建的视频生成类当中去实现视频生成的函数。

⑥调用api实现功能。

基本的实现流程如下现在我将采取代码加文字的形式解释这个项目。

1. start_video_generation

def start_video_generation(request):
    try:
        data = json.loads(request.body)
        prompt = data.get('prompt')
        quality = data.get('quality', 'quality')  # 默认为 'quality'
        fps = data.get('fps', 30)  # 默认为 30
        if not prompt:
            return JsonResponse({'error': '提示词为必填项'}, status=400)
        task = generate_video.delay(request.user.id, prompt, mode='text', image_url=None, confirmed=False,
                                    quality=quality, fps=fps)
        logger.info(f"任务 {task.id} 已提交,状态为 WAITING,用户 {request.user.id}")
        return JsonResponse({'task_id': task.id, 'status': 'WAITING'})
    except json.JSONDecodeError:
        logger.error("start_video_generation 中的 JSON 无效")
        return JsonResponse({'error': '无效的 JSON'}, status=400)
    except Exception as e:
        logger.error(f"任务提交失败: {str(e)}")
        return JsonResponse({'error': f'任务提交失败: {str(e)}'}, status=500)
  • 功能:接收文本提示词,提交文本生成视频的异步任务,返回任务 ID 和状态。

    • 验证请求中是否包含 prompt(提示词),缺失则返回 400 错误。

    • 调用 Celery 任务 generate_video,参数为用户 ID、提示词、生成模式(text)等。

    • 记录任务日志并返回任务 ID 和初始状态(WAITING)。

  • 技术点

    • Django REST Framework 装饰器:@api_view(['POST'])(指定 POST 请求)、@permission_classes([IsAuthenticated])(需登录验证)。

    • CSRF 豁免:@csrf_exempt(允许跨域请求)。

    • JSON 解析:json.loads(request.body) 解析请求体。

    • 异步任务:Celery 的 delay() 方法提交异步任务,返回任务 ID。

    • 日志记录:logger.info 记录任务提交信息。

    • 错误处理:捕获 JSON 解析错误和通用异常,返回对应错误信息。

2. start_image_video_generation

def start_image_video_generation(request):
    try:
        data = json.loads(request.body)
        prompt = data.get('prompt')
        image_url = data.get('image_url')
        quality = data.get('quality', 'quality')  # 默认为 'quality'
        fps = data.get('fps', 30)  # 默认为 30
        if not prompt or not image_url:
            return JsonResponse({'error': '提示词和图片 URL 为必填项'}, status=400)
        task = generate_video.delay(request.user.id, prompt, mode='image', image_url=image_url, confirmed=False,
                                    quality=quality, fps=fps)
        logger.info(f"任务 {task.id} 已提交,状态为 WAITING,图片视频,用户 {request.user.id}")
        return JsonResponse({'task_id': task.id, 'status': 'WAITING'})
    except json.JSONDecodeError:
        logger.error("start_image_video_generation 中的 JSON 无效")
        return JsonResponse({'error': '无效的 JSON'}, status=400)
    except Exception as e:
        logger.error(f"任务提交失败: {str(e)}")
        return JsonResponse({'error': f'任务提交失败: {str(e)}'}, status=500)
  • 功能:接收文本提示词和图片 URL,提交图片生成视频的异步任务,返回任务 ID 和状态。

    • 验证 prompt 和 image_url 是否存在,缺失则返回 400 错误。

    • 调用 Celery 任务 generate_video,生成模式为 image

    • 记录日志并返回任务 ID 和状态。

  • 技术点

    • 同 start_video_generation 的装饰器(@api_view@permission_classes@csrf_exempt)。

    • JSON 解析与参数验证:检查图片 URL 是否存在。

    • Celery 异步任务:提交带图片参数的生成任务。

    • 日志与错误处理:同上。

3. start_frames_video_generation

def start_frames_video_generation(request):
    try:
        data = json.loads(request.body)
        prompt = data.get('prompt')
        image_url = data.get('image_url')
        quality = data.get('quality', 'quality')  # 默认为 'quality'
        fps = data.get('fps', 30)  # 默认为 30
        if not prompt or not image_url or not isinstance(image_url, list) or len(image_url) != 2:
            return JsonResponse({'error': '提示词和图片 URL(包含2个URL的列表)为必填项'}, status=400)
        task = generate_video.delay(request.user.id, prompt, mode='frames', image_url=image_url, confirmed=False,
                                    quality=quality, fps=fps)
        logger.info(f"任务 {task.id} 已提交,状态为 WAITING,首尾帧视频,用户 {request.user.id}")
        return JsonResponse({'task_id': task.id, 'status': 'WAITING'})
    except json.JSONDecodeError:
        logger.error("start_frames_video_generation 中的 JSON 无效")
        return JsonResponse({'error': '无效的 JSON'}, status=400)
    except Exception as e:
        logger.error(f"任务提交失败: {str(e)}")
        return JsonResponse({'error': f'任务提交失败: {str(e)}'}, status=500)
  • 功能:接收文本提示词和两个图片 URL(首尾帧),提交首尾帧生成视频的异步任务,返回任务 ID 和状态。

    • 验证 promptimage_url(必须是包含 2 个 URL 的列表)是否符合要求。

    • 调用 Celery 任务 generate_video,生成模式为 frames

    • 记录日志并返回任务 ID 和状态。

  • 技术点

    • 同前两个生成接口的装饰器和请求处理方式。

    • 参数类型验证:检查 image_url 是否为列表且长度为 2。

    • Celery 异步任务:支持多图片输入的视频生成。

5. get_task_status
def get_task_status(request, task_id):
    try:
        task = AsyncResult(task_id)
        logger.info(f"检查任务 {task_id} 的状态: 状态={task.state}, 结果={task.result}")
        if task.state in ['PENDING', 'PROCESSING', 'WAITING', 'SUCCESS']:
            return JsonResponse({'status': task.state, 'result': task.result, 'error': None})
        elif task.state == 'FAILURE':
            return JsonResponse({'status': task.state, 'result': None, 'error': str(task.result)})
        else:
            logger.warning(f"任务 {task_id} 的状态未知: {task.state}")
            return JsonResponse({'status': task.state, 'result': None, 'error': '未知任务状态'})
    except Exception as e:
        logger.error(f"任务状态检查失败,任务 {task_id}: {str(e)}")
        return JsonResponse({'error': f'任务状态检查失败: {str(e)}'}, status=500)
  • 功能:确认待处理的视频生成任务,重新提交带确认状态的异步任务。

    • 验证请求中是否包含 task_id,通过 AsyncResult 获取原任务状态。

    • 检查原任务是否处于 WAITING 状态,否则返回错误。

    • 从原任务结果中提取参数,调用 generate_video 并标记 confirmed=True,返回新任务 ID。

  • 技术点

    • Celery 任务状态查询:AsyncResult(task_id) 获取任务状态和结果。

    • 状态校验:确保原任务处于可确认状态。

    • 异步任务二次提交:基于原任务参数生成新的确认任务。

6. proxy_video
def proxy_video(request):
    if request.method == 'GET':
        video_url = request.GET.get('url')
        is_download = request.GET.get('download', 'false').lower() == 'true'

        if not video_url:
            logger.error(f"用户 {request.user.id} 请求代理视频失败: 缺少视频 URL")
            return JsonResponse({'error': '视频 URL 为必填项'}, status=400)

        # 验证 URL 格式
        if not re.match(r'^https?://', video_url):
            logger.error(f"用户 {request.user.id} 请求代理视频失败: 无效的视频 URL {video_url}")
            return JsonResponse({'error': '无效的视频 URL'}, status=400)

        try:
            # 查询 VideoHistory 获取视频元数据(用于动态文件名)
            video_history = VideoHistory.objects.filter(user=request.user, video_url=video_url).first()
            filename = 'generated_video.mp4'
            if video_history:
                # 使用 prompt 和时间戳生成文件名
                prompt_snippet = video_history.prompt[:30].replace(' ', '_') if video_history.prompt else 'video'
                timestamp = video_history.created_at.strftime('%Y%m%d_%H%M%S')
                filename = f"{prompt_snippet}_{timestamp}.mp4"

            # 转发 Range 头(用于播放时的流式传输)
            headers = {}
            if 'Range' in request.headers and not is_download:
                headers['Range'] = request.headers['Range']

            response = requests.get(video_url, stream=True, headers=headers, timeout=10)
            response.raise_for_status()

            content_type = response.headers.get('Content-Type', 'video/mp4')
            headers = {
                'Content-Type': content_type,
            }

            # 如果是下载请求,添加 Content-Disposition 头
            if is_download:
                headers['Content-Disposition'] = f'attachment; filename="{quote(filename)}"'

            # 处理范围请求(用于播放)
            if response.status_code == 206 and not is_download:
                headers['Content-Range'] = response.headers.get('Content-Range')
                headers['Accept-Ranges'] = 'bytes'
  • 功能:代理视频文件的流式传输或下载,支持断点续传。

    • 接收视频 URL 和下载标识(download),验证 URL 合法性。

    • 从 VideoHistory 模型查询视频元数据,生成动态文件名。

    • 转发 HTTP 请求头(如 Range 用于断点续传),流式返回视频内容。

    • 支持播放(流式传输)和下载(添加 Content-Disposition 头)。

  • 技术点

    • 流式响应:StreamingHttpResponse 实现大文件分块传输。

    • HTTP 头处理:转发 Range 头支持断点续传,设置 Content-Disposition 控制下载。

    • 第三方请求:requests.get(stream=True) 流式获取远程视频。

    • 数据库查询:VideoHistory.objects.filter 获取视频关联的用户数据。

    • URL 验证:正则表达式 re.match 检查 URL 格式(http:// 或 https://)。

7. video_history
def video_history(request):
    try:
        histories = VideoHistory.objects.filter(user=request.user)
        serializer = VideoHistorySerializer(histories, many=True)
        return JsonResponse({'code': 200, 'data': serializer.data})
    except Exception as e:
        logger.error(f"获取视频历史记录失败: {str(e)}")
        return JsonResponse({'error': f'获取视频历史记录失败: {str(e)}'}, status=500)
  • 功能:获取当前登录用户的视频生成历史记录。

    • 查询 VideoHistory 模型中当前用户的所有记录。

    • 使用 VideoHistorySerializer 序列化数据并返回。

  • 技术点

    • 数据库查询:filter(user=request.user) 筛选当前用户数据。

    • 序列化:VideoHistorySerializer 将模型实例转换为 JSON 格式。

    • 权限控制:@permission_classes([IsAuthenticated]) 确保仅登录用户可访问。

5.2通用技术点

  • 权限控制:通过 IsAuthenticated 限制接口仅登录用户可访问。

  • 日志系统logging.getLogger 记录接口调用、错误等信息。

  • 错误处理:捕获 JSON 解析错误、数据库异常、网络请求异常等,返回结构化错误响应。

  • 异步任务:基于 Celery 实现视频生成任务的异步处理,避免阻塞主线程。

  • HTTP 响应:使用 JsonResponse 返回 JSON 数据,StreamingHttpResponse 处理流式内容。

6、前端实现

前端使用Vue3实现,实现界面美观及稳定
实现的关键点:
①使用轮询解决超时问题

②使用scss实现界面样式美观

③Element_plus实现界面的稳定性

<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
import { ElTabs, ElTabPane, ElInput, ElButton, ElUpload, ElIcon, ElMessage } from 'element-plus';
import { Plus, Download } from '@element-plus/icons-vue';

// 配置axios认证头
const token = localStorage.getItem('token');
if (token) {
  axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}

// 生成模式
const mode = ref('text'); // text, image, frames, config

// 表单数据
const formData = ref({
  content: '' // 提示词
});

// 视频配置数据
const videoConfig = ref({
  frameRate: 30, // 帧率
  quality: 'speed' // 质量
});

// 图片相关
const imageUrl = ref('');
const firstFrameBase64 = ref('');
const lastFrameBase64 = ref('');

// 生成相关
const videoUrl = ref('');
const loading = ref(false);
const polling = ref(false);
const waiting = ref(false);
const error = ref('');
const attempts = ref(0);
const maxAttempts = 120;
const taskId = ref('');

// 处理图片上传
const handleImageUpload = (file: File | undefined, type: 'image' | 'first' | 'last') => {
  if (!file) return false;
  const reader = new FileReader();
  reader.onload = (e) => {
    const base64 = e.target?.result as string;
    if (type === 'image') {
      imageUrl.value = base64;
    } else if (type === 'first') {
      firstFrameBase64.value = base64;
    } else if (type === 'last') {
      lastFrameBase64.value = base64;
    }
  };
  reader.readAsDataURL(file);
  return false;
};

// 移除图片
const removeImage = (type: 'image' | 'first' | 'last') => {
  if (type === 'image') {
    imageUrl.value = '';
  } else if (type === 'first') {
    firstFrameBase64.value = '';
  } else if (type === 'last') {
    lastFrameBase64.value = '';
  }
};

// 生成视频
const generate = async () => {
  if (!token) {
    error.value = '请先登录';
    ElMessage.error(error.value);
    return;
  }
  if (!formData.value.content) {
    error.value = '提示词不能为空';
    ElMessage.error(error.value);
    return;
  }

  loading.value = true;
  error.value = '';
  videoUrl.value = '';
  waiting.value = false;
  polling.value = false;
  attempts.value = 0;
  taskId.value = '';

  let endpoint = 'start-video-generation/';
  let payload: any = {
    prompt: formData.value.content,
    quality: videoConfig.value.quality,
    fps: videoConfig.value.frameRate
  };

  // 图生视频模式
  if (mode.value === 'image') {
    if (!imageUrl.value) {
      error.value = '图片不能为空';
      ElMessage.error(error.value);
      loading.value = false;
      return;
    }
    endpoint = 'start-image-video-generation/';
    payload = {
      prompt: formData.value.content,
      image_url: imageUrl.value,
      quality: videoConfig.value.quality,
      fps: videoConfig.value.frameRate
    };
  }

  // 首尾帧生视频模式
  else if (mode.value === 'frames') {
    if (!firstFrameBase64.value || !lastFrameBase64.value) {
      error.value = '首帧和尾帧不能为空';
      ElMessage.error(error.value);
      loading.value = false;
      return;
    }
    endpoint = 'start-frames-video-generation/';
    payload = {
      prompt: formData.value.content,
      image_url: [firstFrameBase64.value, lastFrameBase64.value],
      quality: videoConfig.value.quality,
      fps: videoConfig.value.frameRate
    };
  }

  try {
    const submitRes = await axios.post(`http://127.0.0.1:8000/api/videotest/${endpoint}`, payload, { timeout: 60000 });
    console.log('start response:', submitRes.data);
    taskId.value = submitRes.data.task_id;
    if (!taskId.value) {
      error.value = submitRes.data.error || '任务提交失败:无任务 ID';
      ElMessage.error(error.value);
      return;
    }

    if (submitRes.data.status === 'WAITING') {
      waiting.value = true;
    } else {
      error.value = `任务状态异常: ${submitRes.data.status}`;
      ElMessage.error(error.value);
      console.warn('Unexpected status, attempting to poll:', submitRes.data.status);
      polling.value = true;
      pollForResult(taskId.value);
    }
  } catch (err: any) {
    error.value = `任务提交失败: ${err.response?.data?.error || err.message || '未知错误'}`;
    ElMessage.error(error.value);
    console.error('start error:', err, 'Response data:', err.response?.data);
  } finally {
    loading.value = false;
  }
};

// 确认生成
const confirm = async () => {
  if (!taskId.value) {
    error.value = '无有效任务 ID';
    ElMessage.error(error.value);
    console.error('No valid taskId for confirm');
    return;
  }

  loading.value = true;
  error.value = '';

  try {
    const confirmRes = await axios.post('http://127.0.0.1:8000/api/videotest/confirm-video-generation/', {
      task_id: taskId.value,
    }, { timeout: 60000 });

    console.log('confirm-video-generation response:', confirmRes.data);
    taskId.value = confirmRes.data.task_id;
    if (!taskId.value || confirmRes.data.status !== 'PROCESSING') {
      error.value = confirmRes.data.error || '任务确认失败';
      ElMessage.error(error.value);
      console.error('Confirm failed:', confirmRes.data);
      return;
    }

    polling.value = true;
    waiting.value = false;
    pollForResult(taskId.value);
  } catch (err: any) {
    error.value = `任务确认失败: ${err.response?.data?.error || err.message || '未知错误'}`;
    ElMessage.error(error.value);
    console.error('confirm-video-generation error:', err, 'Response data:', err.response?.data);
  } finally {
    loading.value = false;
  }
};

// 新增: 加载视频 Blob 的辅助函数(修复播放问题)
const loadVideoBlob = async (proxyUrl: string) => {
  try {
    const response = await fetch(proxyUrl, {
      headers: {
        Authorization: `Bearer ${token}` // 添加认证头
      }
    });
    if (!response.ok) {
      throw new Error(`获取视频失败: ${response.statusText}`);
    }
    const blob = await response.blob();
    videoUrl.value = URL.createObjectURL(blob); // 转换为 Blob URL
    ElMessage.success('视频加载成功');
  } catch (err: any) {
    error.value = `加载视频失败: ${err.message}`;
    ElMessage.error(error.value);
    console.error('加载视频错误:', err);
  }
};

// 轮询任务状态(修改成功分支,使用 Blob URL 播放)
const pollForResult = async (taskId: string) => {
  attempts.value = 0;
  const baseDelay = 10000;
  const maxDelay = 30000;

  const poll = async () => {
    try {
      const res = await axios.get(`http://127.0.0.1:8000/api/videotest/get-task-status/${taskId}/`, {
        timeout: 20000,
      });
      console.log('get-task-status response:', res.data);
      const { status, result, error: taskError } = res.data;

      if (status === 'SUCCESS' && result && result.url) {
        const proxyUrl = `http://127.0.0.1:8000/api/videotest/proxy-video/?url=${encodeURIComponent(result.url)}`;
        await loadVideoBlob(proxyUrl); // 使用 Blob 加载视频
        polling.value = false;
        ElMessage.success('视频生成成功!');
      } else if (status === 'FAILURE') {
        error.value = taskError || '视频生成失败';
        ElMessage.error(error.value);
        polling.value = false;
      } else if (status === 'PENDING' || status === 'PROCESSING') {
        if (attempts.value < maxAttempts) {
          const delay = Math.min(baseDelay * Math.pow(2, attempts.value / 2), maxDelay);
          attempts.value++;
          setTimeout(poll, delay);
        } else {
          error.value = '任务超时,请检查后端任务状态';
          ElMessage.error(error.value);
          polling.value = false;
        }
      } else if (status === 'WAITING') {
        error.value = '任务仍未确认,请点击确认生成';
        ElMessage.error(error.value);
        polling.value = false;
        waiting.value = true;
      } else {
        error.value = `未知任务状态: ${status}`;
        ElMessage.error(error.value);
        polling.value = false;
      }
    } catch (err: any) {
      console.error('get-task-status error:', err, 'Response data:', err.response?.data);
      if (err.code === 'ECONNABORTED' || err.response?.status === 504) {
        if (attempts.value < maxAttempts) {
          const delay = Math.min(baseDelay * Math.pow(2, attempts.value / 2), maxDelay);
          attempts.value++;
          setTimeout(poll, delay);
        } else {
          error.value = '任务超时,请检查后端任务状态';
          ElMessage.error(error.value);
          polling.value = false;
        }
      } else {
        error.value = `查询结果失败: ${err.response?.data?.error || err.message || '未知错误'}`;
        ElMessage.error(error.value);
        polling.value = false;
      }
    }
  };
  poll();
};

// 处理视频播放错误
const handleVideoError = (event: Event) => {
  console.error('Video playback error:', event);
  error.value = '视频播放失败,请检查链接或网络';
  ElMessage.error(error.value);
};

// 重试功能
const retry = () => {
  error.value = '';
  attempts.value = 0;
  videoUrl.value = '';
  waiting.value = false;
  polling.value = false;
  taskId.value = '';
  generate();
};
const downloading = ref(false);
// 下载视频(假按钮)
const downloadVideo = async (url: string) => {
  if (downloading.value) return;
  downloading.value = true;
  try {
    ElMessage.info('正在准备下载,请稍候...');
    const downloadUrl = `${url}${url.includes('?') ? '&' : '?'}download=true`;
    const response = await fetch(downloadUrl, {
      headers: {
        Authorization: `Bearer ${token}`
      }
    });

    if (!response.ok) {
      throw new Error(`下载失败: ${response.statusText}`);
    }

    const blob = await response.blob();
    const downloadUrlObj = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrlObj;
    link.download = 'generated_video.mp4';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrlObj);
    ElMessage.success('视频下载已开始!');
  } catch (err: any) {
    error.value = `下载失败: ${err.message || '未知错误'}`;
    ElMessage.error(error.value);
    console.error('Download error:', err);
  } finally {
    downloading.value = false;
  }
};
</script>

一、整体功能实现

该代码实现了一个 AI 视频生成平台的前端页面,核心功能是允许用户通过不同模式(文生视频、图生视频、首尾帧生视频)生成视频,并支持视频预览和下载。整个平台整体流程包括:用户输入配置 → 提交生成任务 → 实时监控任务进度 → 预览生成结果 → 下载视频文件。

二、关键功能模块

  1. 用户认证与请求配置

    • 从 localStorage 获取 token 并配置 axios 请求头,实现身份验证
    • 所有 API 请求自动携带 Authorization 令牌,确保接口安全访问
  2. 多模式视频生成

    • 文生视频:通过文本提示词生成视频
    • 图生视频:基于单张图片和提示词生成视频
    • 首尾帧生视频:根据首帧和尾帧图片及提示词生成过渡视频
    • 视频配置:可设置帧率(30fps/60fps)和质量模式(速度优先 / 质量优先)
  3. 任务管理流程

    • 任务提交:根据不同模式向后端发送相应参数
    • 任务确认:支持待处理任务的确认机制
    • 进度监控:通过轮询机制实时获取任务状态
    • 结果处理:视频生成成功后加载并展示视频
  4. 媒体处理功能

    • 图片上传:支持首帧、尾帧等图片上传并预览
    • 视频预览:使用 HTML5 video 标签实现视频播放
    • 视频下载:通过 Blob 对象和 URL.createObjectURL 实现视频下载
  5. 用户交互反馈

    • 加载状态显示:任务提交和处理过程中的动画提示
    • 错误处理:各类操作错误的提示和重试机制
    • 状态指示:清晰展示视频生成各阶段状态

三、关键技术点解析

  1. Vue 3 + TypeScript 组合式 API

    • 使用<script setup lang="ts">实现组件逻辑,提升类型安全性
    • 通过ref创建响应式数据,管理表单状态、媒体资源和任务信息
  2. Axios 网络请求

    • 配置全局请求头实现身份验证
    • 处理不同类型的 HTTP 请求(POST 提交任务、GET 查询状态)
    • 设置超时处理和错误捕获机制
  3. 文件处理技术

    • FileReader API:将上传的图片转换为 Base64 格式预览
    • Blob 与 Object URL:处理视频流,实现前端视频预览和下载
    • 断点续传支持:通过 Range 请求头实现大视频文件的断点续传
  4. 任务轮询机制

    • 指数退避策略:随着尝试次数增加,逐步延长轮询间隔(10s 到 30s)
    • 最大尝试限制:最多 120 次尝试,防止无限轮询
    • 状态分支处理:根据不同任务状态(SUCCESS/FAILURE/PENDING 等)执行相应逻辑
  5. Element Plus 组件集成

    • 表单组件:ElInput、ElSelect 处理用户输入
    • 上传组件:ElUpload 实现图片上传功能
    • 导航组件:ElTabs 实现不同生成模式的切换
    • 反馈组件:ElMessage 提供操作结果提示
  6. 动画与交互效果

    • CSS 动画:实现标题浮动、加载动画、状态指示等视觉效果
    • 过渡效果:按钮悬停、点击反馈等微交互
    • 响应式设计:适配不同屏幕尺寸的布局调整
  7. 错误处理机制

    • 输入验证:检查必填项和格式合法性
    • 网络错误处理:捕获请求失败、超时等异常
    • 播放错误处理:视频加载和播放失败的提示
  8. 安全措施

    • 权限控制:未登录用户无法提交生成任务
    • URL 验证:检查图片和视频 URL 的合法性
    • 认证保护:所有敏感操作都需要有效的 token

该代码通过组合现代前端技术,实现了一个功能完整、用户体验良好的 AI 视频生成平台界面,同时兼顾了代码的可维护性和扩展性。

7、项目总结

“言映 AI 视频生成” V1.0 项目已圆满完成需求文档既定目标,实现从文本到视频的全流程自动化,技术架构稳定、功能覆盖全面、用户体验良好,为不同场景用户提供了低门槛、高效率的视频生成解决方案。后续将基于现存不足与用户反馈持续迭代,进一步提升功能完整性、审核精度与用户体验,推动产品向更成熟、更贴合市场需求的方向发展。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐