ffmpeg前端或者后端实现视频压缩上传

后端实现视频压缩上传到minio

首先你需要在电脑下载ffmpeg包,然后在电脑配置环境变量

复制路径到环境变量

1、controller层

@RequestMapping("/upload")
public class UploadController{
@ApiOperation(value = "视频上传")
@PostMapping("/uploadVideo")  
public Result uploadVideo(@RequestPart("file") MultipartFile file) {
        return result = bizUploadService.uploadVideo(file);
      }
}

2、service层

此时minio的上传这里已经做成一个业务层可直接调用,具体实现方式大家可以看之前写的封装成的jar包

@Service
public class upload{
@Autowired
    private MinoService minoService;
 
/**
     * 上传视频压缩处理
     *
     * @param file
     * @return
     */
    public Result uploadVideo(MultipartFile file) {
        if (file.isEmpty()) {
            return Result.error("上传视频为不存在");
        }
        // 临时保存上传的文件
        File tempFile = null;
        String outputFilePath =null;
        MockMultipartFile multipartFile =null;
        String uploadFilePath =null;
        try {
            tempFile = File.createTempFile("temp-video-", ".mp4");
            file.transferTo(tempFile);
            // FFmpeg压缩命令示例(需要根据实际需求调整参数)
            outputFilePath = tempFile.getAbsolutePath().replace(".mp4", "-compressed.mp4");
            String ffmpegCmd = "ffmpeg -i " + tempFile.getAbsolutePath() + " -c:v libx264 -preset veryfast -crf 23 -c:a copy " + outputFilePath;
            ProcessBuilder pb = new ProcessBuilder(Arrays.asList(ffmpegCmd.split(" ")));
            pb.inheritIO().start().waitFor();

            //根据文件输出路径反编译为MockMultipartFile上传到minio
             multipartFile = convertToFileMockMultipartFile(outputFilePath);
            //上传视频到minio
            uploadFilePath = minoService.uploadFile("effort", file);
        } catch (IOException e) {
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return Result.success(uploadFilePath);
    }
    //根绝文件路径编译成MockMultipartFile上传到minio
    private static MockMultipartFile convertToFileMockMultipartFile(String filePath) throws IOException {
        File file = new File(filePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        String fileName = file.getName();
        return new MockMultipartFile("file", fileName, "multipart/form-data", fileInputStream);
    }
}

此时的后端视频压缩上传做的差不多了,但是对于大视频压缩会造成大量的资源占用,影响性能

下面有前端压缩方法

前端视频实现压缩:

这里用的是vue3,配置文件是vite.config.js

<template>
  <div class="video-box">
    <video id="video" controls object-fill="fill"></video><br />
    <input id="upload" type="file" accept="video/mp4" capture="camcorder" @change="upload"><br/>
    <button @click="uploadVideo">上传</button>
  </div>
</template>

<script>
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'

export default {
  data () {
      return {
          msg: '',
          videoWidth: '',
          videoHeight: '',
          duration: ''
      }
  },

  methods: {
      // 选择文件
      async upload (e) {
          console.log('start', e)
          console.log('start', e.target.files[0])
          var _this = this
          if (e.target.files[0]) {
              var filename = e.target.files[0].name
              var filetype = e.target.files[0].type

              const videoUrl = _this.getObjectURL(e.target.files[0])
              const video = document.getElementById('video')
              video.src = videoUrl

              this.getVideoData().then((videoObj) => {
                  const file = e.target.files[0]
                  console.log('videoObj:', videoObj)
                  const { width, height } = videoObj
                  const result = _this.squeezVideo(file, filename, filetype, width, height, _this.msg)
                  result.then(res => {
                      console.log('resultFile', res)
                  })
              })
          }
      },
      // 压缩视频
      async squeezVideo (file, filename, filetype, width, height) {
          console.log('squeezingVideo file name:  ', file.name)
          console.log('squeezingVideo file type:  ', file.type)
          console.log('squeezingVideo file path:  ', file.path)
          console.log('squeezingVideo file size:  ', file.size)
          console.log('squeezingVideo file lastModified:  ', file.lastModified)
          console.log('squeezingVideo file lastModifiedDate:  ', file.lastModifiedDate)
          const _this = this
          // 分辨率
          const resolution = `${width / 2}x${height / 2}`
          // 实例化ffmpeg
          const ffmpeg = createFFmpeg({
              // ffmpeg路径
              corePath: 'ffmpeg-core.js',
              // 日志
              log: true,
              // 进度
              progress: ({ ratio }) => {
                  _this.msg = `完成率: ${(ratio * 100.0).toFixed(1)}%`
              }
          })
          var { name } = file
          this.msg = '正在加载 ffmpeg-core.js'
          // 开始加载
          await ffmpeg.load()
          this.msg = '开始压缩'
          // 把文件加到ffmpeg   写文件
          ffmpeg.FS('writeFile', name, await fetchFile(file))
          // await ffmpeg.run('-i', name, '-b', '2000000', '-fs', '4194304', '-preset medium', 'superfast', 'put.mp4')
          // 开始压缩视频
          await ffmpeg.run('-i', name, '-b', '2000000', '-crf', '23', '-fs', '4194304', '-s', resolution, 'put.mp4')
          this.msg = '压缩完成'
          // 压缩所完成,   读文件  压缩后的文件名称为 put.mp4
          const data = ffmpeg.FS('readFile', 'put.mp4')
          // 转换压缩后的视频格式  当前为 blob 格式
          var filed = _this.transToFile(data)
          console.log('transToFile: ', filed)
          return new Promise((resolve, reject) => {
              if (filed) {
                  resolve({
                      squzingFile: filed
                  })
              }
          })
      },
      // 获取视频的宽高分辨率
      getVideoData () {
          return new Promise((resolve, reject) => {
              const videoElement = document.getElementById('video')
              videoElement.addEventListener('loadedmetadata', function () {
                  resolve({
                      width: this.videoWidth,
                      height: this.videoHeight,
                      duration: this.duration
                  })
              })
          })
      },
      // 获取上传视频的url
      getObjectURL (file) {
          let url = null
          window.URL = window.URL || window.webkitURL
          if (window.URL) {
              url = window.URL.createObjectURL(file)
          } else {
              url = URL.createObjectURL(file)
          }
          return url
      },
      // 类型转换 blob 转换 file
      transToFile (data) {
          console.log(data)
          const _this = this
          var file = []
          // 转换bolb类型
          const blob = new Blob([data], { type: 'text/plain;charset=utf-8' })
          // 这么写是因为文件转换是异步任务
          const transToFile = async (blob, fileName, fileType) => {
              return new window.File([blob], fileName, { type: fileType })
          }
          const textContain = transToFile(blob, 'put.mp4', 'video/mp4')
          // 转换完成后可以将file对象传给接口
          textContain.then((res) => {
              file.push(res)
              console.log('res', res)
              // _this.confirm(file)
          })
          return file
      }
  }
}
</script>

过程中会出现错误ReferenceError: SharedArrayBuffer is not defined

记得再vite.config.js中配置·

server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp'
    },

如果用的是vue.config.js配置

  devServer: {
    headers: {
      // 如果需要用到ffmpeg合并视频,需要将COEP和COOP打开,来确保ShareArrayBuffer能够正常使用
      'Cross-Origin-Embedder-Policy': 'require-corp',
      'Cross-Origin-Opener-Policy': 'same-origin',
    }
  }

这样不出问题就可以直接运行

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在前端使用FFmpeg进行视频压缩,你可以使用FFmpegJavaScript库,例如`ffmpeg.js`或`fluent-ffmpeg`。以下是使用`ffmpeg.js`进行前端视频压缩的基本步骤: 1. 下载`ffmpeg.js`:从FFmpeg官方的GitHub存储库(https://github.com/ffmpegwasm/ffmpeg.wasm)下载`ffmpeg.js`文件。 2. 引入`ffmpeg.js`:将下载的`ffmpeg.js`文件放置在你的项目中,并在HTML文件中引入它。 ```html <script src="path/to/ffmpeg.js"></script> ``` 3. 初始化FFmpeg:在JavaScript代码中,使用以下代码初始化FFmpeg。 ```javascript const ffmpeg = createFFmpeg({ log: true, }); await ffmpeg.load(); ``` 4. 选择和处理视频文件:你可以通过文件输入元素或其他方式让用户选择要压缩的视频文件。一旦用户选择了视频文件,你可以使用以下代码加载和处理视频。 ```javascript const fileInput = document.querySelector('input[type="file"]'); const file = fileInput.files[0]; await ffmpeg.write('input.mp4', await file.arrayBuffer()); await ffmpeg.run('-i input.mp4 output.mp4'); ``` 在上述代码中,我们首先将用户选择的视频文件写入到FFmpeg的虚拟文件系统中(此处命名为`input.mp4`),然后运行FFmpeg命令进行视频压缩。 5. 获取压缩后的视频:使用以下代码从虚拟文件系统中获取压缩后的视频文件。 ```javascript const compressedVideoData = await ffmpeg.read('output.mp4'); const compressedVideoBlob = new Blob([compressedVideoData.buffer], { type: 'video/mp4' }); const compressedVideoURL = URL.createObjectURL(compressedVideoBlob); ``` 上述代码将压缩后的视频文件读取为`Uint8Array`,然后创建一个`Blob`对象,并使用`URL.createObjectURL()`方法创建一个URL,以便你可以在页面中显示或下载压缩后的视频。 请注意,这只是使用`ffmpeg.js`进行前端视频压缩的基本步骤。你可以根据需要进一步定制和处理视频。确保在实际使用中仔细阅读和理解`ffmpeg.js`的文档和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值