vue使用gitshot生成gif问题

 更新时间:2024年03月06日 09:43:57   作者:baorant在写代码  
这篇文章主要介绍了vue使用gitshot生成gif问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

问题背景

本文将介绍vue中使用gitshot生成gif。

问题分析

解决思路

使用input组件上传一个视频,获取视频文件后用一个video组件进行播放,播放过程进行截图生成图片数组。

demo演示上传一个视频,然后生成对应的gif。

注意事项

html中使用video标签调用本地视频结果只有音频没有视频画面问题?

解决思路

html中 video 标签支持的视频格式,一共支持三种格式:

  • Ogg
  • MPEG4
  • WebM

但这三种格式对于浏览器的兼容性却各不同。

比如MP4格式,MP4只是一个容器,里面还有一个叫编码器的东西。

格式虽然都是MP4但是html中只支持H.264的编码格式。

所以要用软件来转码。

  • MP4 = MPEG 4文件使用 H264 视频编解码器和AAC音频编解码器
  • WebM = WebM 文件使用 VP8 视频编解码器和 Vorbis 音频编解码器
  • Ogg = Ogg 文件使用 Theora 视频编解码器和 Vorbis音频编解码器。

可使用格式工厂软件对本地视频格式进行处理。

问题解决

(1)安装所需的npm包

npm install gifshot --save

(2)完整代码如下:

<template>
  <div style="display: flex; flex-direction: column;">
    <!-- 选择要上传的视频 -->
    <div style="display: flex;">
      <input type="file" ref="videoInput" accept="video/mp4" style="margin: 15px;">
      <button @click="handleFileChange" style="height: 30px; width: 50px; margin: 15px;">确定</button>
    </div>

    <video style="width: 400px;height: 400px; margin: 15px;" ref="videoRef" :src="videoUrl" controls>
    </video>
    <div style="margin: 15px;">输出gif如下:</div>
  </div>
</template>
<script>
import gifshot from 'gifshot';
export default {
  data() {
    return {
      videoUrl: null,
      interval: null,
      clipImgs: [],
      delay: 200,
    }
  },
  methods: {
    handleFileChange() {
      // 获取选择的视频文件
      this.selectedVideo = this.$refs.videoInput.files[0];
      console.log(this.selectedVideo);

      if (!this.selectedVideo) {
        console.log('请选择文件');
        return;
      }
      this.videoUrl = '';
      this.convertFileToBase64(this.selectedVideo)
        .then(base64Data => {
          this.videoUrl = base64Data;
          console.log('this videoUrl', this.videoUrl);
          this.start() //视频截图并转成gif
        })
        .catch(error => {
          console.error('Error:', error);
        });
    },

    // 文件转成base64
    convertFileToBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    },
    // base64转image
    getImageFromBase64(base64Image) {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.src = base64Image;
        img.onload = () => resolve(img);
        img.onerror = reject;
      });
    },

    start() {
      console.log('start');
      // 每次开始重置以下值
      clearInterval(this.interval);

      let video = this.$refs.videoRef; //获取video元素
      console.log('start', video);
      video.addEventListener('canplay', function () {
        console.log('canplay', video);
        video.play();
      });
      let that = this;

      video.addEventListener('play', function () {
        var canvas = document.createElement('canvas');

        // 根据视频大小调整画布尺寸
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        console.log('play', video);

        // 获取上下文对象
        var context = canvas.getContext('2d');

        this.interval = setInterval(() => {
          context.drawImage(video, 0, 0);  // 将视频内容绘制到画布上
          let screenshotDataURL = canvas.toDataURL(); // 转成Base64
          console.log(screenshotDataURL, that.clipImgs);
          that.clipImgs.push(screenshotDataURL) //把所有截图放到一个数组里
        }, that.delay)
      });
      // 监听视频播放结束后,说明截图完成。定时器停止,清除定时器缓存,开始转换。
      video.addEventListener('ended', function (e) {
        console.log('stop');
        clearInterval(this.interval)
        this.interval = null
        that.makeGIF()
      })
    },

    async makeGIF() {
      // 使用gifshot,将图片数组转成gif
      gifshot.createGIF({
        gifWidth: 200,
        gifHeight: 200,
        images: this.clipImgs,
        interval: 0.1,
        numFrames: 10,
        frameDuration: 1,
        fontWeight: 'normal',
        fontSize: '16px',
        fontFamily: 'sans-serif',
        fontColor: '#ffffff',
        textAlign: 'center',
        textBaseline: 'bottom',
        sampleInterval: 10,
        numWorkers: 2
      }, function (obj) {
        console.log(obj, " obj");
        if (!obj.error) {
          let image = obj.image;
          let animatedImage = document.createElement('img');
          animatedImage.src = image;
          animatedImage.style = 'margin: 15px';
          document.body.appendChild(animatedImage);
        }
      });
    }
  }
}
</script>

运行结果如下:

选择本地视频文件,确定选择会播放该视频,播放完成生成对应的gif文件。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue整合项目中百度API示例详解

    vue整合项目中百度API示例详解

    这篇文章主要为大家介绍了vue整合项目中百度API示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 深入理解使用Vue实现Context-Menu的思考与总结

    深入理解使用Vue实现Context-Menu的思考与总结

    这篇文章主要介绍了使用Vue实现Context-Menu的思考与总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • vue父子组件传值以及单向数据流问题详解

    vue父子组件传值以及单向数据流问题详解

    大家应该都知道父组件可以向子组件通过属性形式传递参数,传递的参数也可以随时随意修改;但子组件不能修改父组件传递过来的参数,所以下面这篇文章主要给大家介绍了关于vue父子组件传值以及单向数据流问题的相关资料,需要的朋友可以参考下
    2021-09-09
  • vue调用swiper插件步骤教程(最易理解且详细)

    vue调用swiper插件步骤教程(最易理解且详细)

    有时候我们需要在vue中使用轮播组件,如果是在vue组件中引入第三方组件的话,最好通过npm安装,从而进行统一安装包管理,下面这篇文章主要给大家介绍了关于vue调用swiper插件的相关资料,需要的朋友可以参考下
    2023-04-04
  • Vue项目中使用WebUploader实现文件上传的方法

    Vue项目中使用WebUploader实现文件上传的方法

    WebUploader是由 Baidu WebFE(FEX) 团队开发的一个简单的以 HTML5为主 , FLASH为辅 的现代 文件上传组件 。这篇文章主要介绍了在Vue项目中使用WebUploader实现文件上传,需要的朋友可以参考下
    2019-07-07
  • Vue项目中props传值时子组件检测不到的问题及解决

    Vue项目中props传值时子组件检测不到的问题及解决

    这篇文章主要介绍了Vue项目中props传值时子组件检测不到的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 基于Vue实现页面切换左右滑动效果

    基于Vue实现页面切换左右滑动效果

    这篇文章主要为大家详细介绍了基于Vue实现页面切换左右滑动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 解决vue跨域axios异步通信问题

    解决vue跨域axios异步通信问题

    这篇文章主要介绍了解决vue跨域axios异步通信问题,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2019-04-04
  • vue3封装el-pagination分页组件的完整代码

    vue3封装el-pagination分页组件的完整代码

    这篇文章主要介绍了vue3封装el-pagination分页组件的完整代码,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-02-02
  • 使用vue-router设置每个页面的title方法

    使用vue-router设置每个页面的title方法

    下面小编就为大家分享一篇使用vue-router设置每个页面的title方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02

最新评论