思路介绍

在互联网应用中,视频是一种常见的媒体形式,但是视频文件往往占用较大的存储空间和网络带宽,影响用户的体验和效率。为了解决这个问题,我们可以使用视频压缩技术,将视频文件的大小和质量进行平衡,减少视频传输和存储的成本。同时,我们也需要保证视频的清晰度和流畅度,让用户能够观看高质量的视频内容。

本文将介绍如何使用Vue+Springboot框架实现一个视频压缩&清晰播放的前后端应用,主要包括以下几个方面:

  • 前端使用Vue框架搭建一个简单的视频上传和播放界面,使用Element UI组件库提供美观的样式和交互。
  • 后端使用Springboot框架搭建一个RESTful API服务,提供视频上传、压缩、下载和播放的功能,使用FFmpeg工具进行视频压缩处理,使用H2数据库存储视频元数据。
  • 使用axios库实现前后端的数据交互,使用video.js库实现视频播放器的自定义和控制。

技术要点讲解

前端部分

1. 创建Vue项目

我们可以使用Vue CLI工具创建一个Vue项目,命令如下:

vue create video-compression

复制

选择默认的配置即可,等待项目创建完成后,进入项目目录,运行以下命令启动开发服务器:

npm run serve

复制

打开浏览器访问http://localhost:8080/,可以看到一个简单的欢迎页面。

2. 安装依赖库

我们需要安装以下几个依赖库:

  • axios:用于实现前后端的数据交互
  • element-ui:用于提供美观的UI组件
  • video.js:用于实现视频播放器的自定义和控制

运行以下命令安装这些库:

npm install axios element-ui video.js --save

复制

3. 配置Element UI

在main.js文件中,引入element-ui的样式文件和组件库,并注册为全局组件:

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

复制

4. 创建视频上传和播放界面

在src目录下创建一个components文件夹,并在其中创建一个VideoUpload.vue文件,这个文件是我们的视频上传和播放组件。在这个文件中,我们需要定义以下几个数据和方法:

  • videoFile:用于存储用户选择的视频文件对象
  • videoUrl:用于存储用户上传的视频文件的URL地址
  • compressedVideoUrl:用于存储用户下载的压缩后的视频文件的URL地址
  • uploadVideo:用于实现视频文件的上传功能,调用后端的/upload接口,并将返回的URL地址赋值给videoUrl
  • compressVideo:用于实现视频文件的压缩功能,调用后端的/compress接口,并将返回的URL地址赋值给compressedVideoUrl
  • downloadVideo:用于实现视频文件的下载功能,调用后端的/download接口,并将压缩后的视频文件保存到本地
  • playVideo:用于实现视频文件的播放功能,使用video.js库创建一个视频播放器,并将videoUrl或compressedVideoUrl作为视频源

在<template>标签中,我们需要使用element-ui的组件来构建一个简单的界面,包括以下几个部分:

  • 一个el-upload组件,用于选择和上传视频文件,绑定videoFile数据和uploadVideo方法
  • 一个el-button组件,用于触发视频文件的压缩功能,绑定compressVideo方法
  • 一个el-button组件,用于触发视频文件的下载功能,绑定downloadVideo方法
  • 一个el-button组件,用于触发视频文件的播放功能,绑定playVideo方法
  • 一个div元素,用于显示视频播放器,设置id为video-player

VideoUpload.vue文件的完整代码如下:

<template>
  <div class="video-upload">
    <el-upload
      action="#"
      :auto-upload="false"
      :show-file-list="false"
      :before-upload="uploadVideo"
    >
      <el-button type="primary">选择视频</el-button>
    </el-upload>
    <el-button type="success" @click="compressVideo" :disabled="!videoUrl">压缩视频</el-button>
    <el-button type="info" @click="downloadVideo" :disabled="!compressedVideoUrl">下载视频</el-button>
    <el-button type="warning" @click="playVideo" :disabled="!videoUrl && !compressedVideoUrl">播放视频</el-button>
    <div id="video-player"></div>
  </div>
</template>

<script>
import axios from 'axios'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'

export default {
  name: 'VideoUpload',
  data() {
    return {
      videoFile: null,
      videoUrl: '',
      compressedVideoUrl: ''
    }
  },
  methods: {
    uploadVideo(file) {
      this.videoFile = file
      let formData = new FormData()
      formData.append('file', file)
      axios.post('http://localhost:8081/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(res => {
        this.videoUrl = res.data
        this.$message.success('上传成功')
      }).catch(err => {
        console.error(err)
        this.$message.error('上传失败')
      })
      return false
    },
    compressVideo() {
      axios.get('http://localhost:8081/compress', {
        params: {
          url: this.videoUrl
        }
      }).then(res => {
        this.compressedVideoUrl = res.data
        this.$message.success('压缩成功')
      }).catch(err => {
        console.error(err)
        this.$message.error('压缩失败')
      })
    },
    downloadVideo() {
      axios.get('http://localhost:8081/download', {
        params: {
          url: this.compressedVideoUrl
        },
        responseType: 'blob'
      }).then(res => {
        let blob = res.data
        let url = window.URL.createObjectURL(blob)
        let link = document.createElement('a')
        link.href = url
        link.download = this.videoFile.name.replace(/\.\w+$/, '-compressed.mp4')
        link.click()
        window.URL.revokeObjectURL(url)
        this.$message.success('下载成功')
      }).catch(err => {
        console.error(err)
        this.$message.error('下载失败')
      })
    },
    playVideo() {
      let player = videojs('video-player', {
        controls: true,
        autoplay: true,
        preload: 'auto',
        fluid: true,
        sources: [{
          src: this.compressedVideoUrl || this.videoUrl,
          type: 'video/mp4'
        }]
      })
    }
  }
}
</script>

<style scoped>
.video-upload {
  margin: 20px;
}
#video-player {
  width: 800px;
  height: 450px;
}
</style>

如何用FFmpeg进行视频压缩

FFmpeg是一个强大的视频处理工具,可以用来进行视频压缩。视频压缩的原理是降低视频的比特率、分辨率、帧率或编码格式,从而减少视频文件的大小,但同时也会损失一定的视频质量。FFmpeg可以通过命令行参数来控制视频压缩的各种选项,例如:

  • -vcodec:指定视频编码格式,例如libx264(H.264)、libx265(H.265)、libvpx(VP8/VP9)等
  • -crf:指定压缩质量因子,取值范围为0-51,0表示无损,23为默认值,数值越大质量越低
  • -b:v:指定视频比特率,例如1M、500k等
  • -s:指定视频分辨率,例如1280x720、640x480等
  • -r:指定视频帧率,例如30、24、15等

以下是一些使用FFmpeg进行视频压缩的示例:

  • 使用H.264编码格式和23的压缩质量因子压缩视频:
ffmpeg -i input.mp4 -vcodec libx264 -crf 23 output.mp4
  • 使用H.265编码格式和28的压缩质量因子压缩视频:
ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4
  • 使用VP9编码格式和1M的比特率压缩视频:
ffmpeg -i input.mp4 -vcodec libvpx-vp9 -b:v 1M output.webm
  • 将视频分辨率降低为640x480:
ffmpeg -i input.mp4 -s 640x480 output.mp4
  • 将视频帧率降低为15:
ffmpeg -i input.mp4 -r 15 output.mp4