vue 视频添加水印

1,343 阅读3分钟

1.需求背景

其实腾讯云点播的api也支持视频水印,但是只有单个水印,大概效果是这样子的,不满足我们的需求,我们的需求是需要视频中都是水印。 腾讯云点播水印

71b0a92d30f3569bba65347f1dd1909b_1711627428052-92b707aa-8f33-451f-9eb5-550e6b92fbfb_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_633%2Climit_0.png 项目需求的水印(主要是防录屏,最后的实现效果是这样)

6098cd34ce40262f51dd8934a12ba070_1711627529256-89899f93-a1d8-461a-9fcd-14867445d814_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_806%2Climit_0.png

2.实现

a.创建 warterMark.js

392ea6524e17c808ac9e4d012d67ca67_1711903213881-b452d554-2305-4f98-b925-a703f7eab8c1_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png

b.warterMark.js里面的代码

import Vue from 'vue'
 
![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/47b99774e3ec4c3480111c10642a6770~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1457&h=971&s=192075&e=png&b=242520)
Vue.directive('watermark', {
  bind: function(el, binding){
    // 水印文字,父元素,画布宽度,画布高度,字体,文字颜色,画布横坐标
    function addWaterMarker(str, parentNode, width, height, font, textColor, fillTextX = '10'){ 
      // 检查父元素是否包含子元素
      const elementContains = (parent, child) => parent !== child && parent.contains(child);
      const flag = elementContains(parentNode, document.querySelector('canvas'));
      // 防止重复创建
      if (!flag) {
        let can = document.createElement('canvas');
        parentNode.appendChild(can);
        can.width = width || 200;
        can.height = height || 140;
        can.style.display = 'none';
        let cans = can.getContext('2d');
        cans.rotate(-20 * Math.PI / 180);
        cans.font = font || "13px Microsoft Yahei";
        cans.fillStyle = textColor || "#DDDDDD";
        cans.textAlign = 'left';
        cans.textBaseline = 'Middle';
        cans.fillText(str, fillTextX, can.height);
        // 设置背景图(整个项目中都添加水印建议使用此方法)
        // parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
        
        // 创建div 定位覆盖(某个元素,如图片添加水印建议使用此方法)
        let div = document.createElement('div');
        div.id = str;
        div.style.pointerEvents = 'none';
        div.style.top = '0';
        div.style.left = '0';
        div.style.position = 'absolute';
        div.style.zIndex = '100000';
        div.style.width = '100%';
        div.style.height = '100%';
        div.style.background = 'url(' + can.toDataURL('image/png') + ')';
        parentNode.appendChild(div);
      }
    }
    if (binding.value.text) {
      addWaterMarker(binding.value.text, el, binding.value.width, binding.value.height, binding.value.font, binding.value.textColor, binding.value.fillTextX )
    }
  }
})

c.main.js 引入warterMark.js (或者在想要添加的某个页面引入)

import  '@/utils/warterMark.js'

d1470db98011144a0633d036df0ff4bb_1711627702792-b29eda9d-8e8c-4d98-9dbd-d88fad5dd678_x-oss-process=image%2Fformat%2Cwebp.png

d.页面结构(注意水印一定要跟video同级,不要直接加到video上面去,会没有用)

38095df0ebf15a2295fcbe86acf433bd_1711627903485-f85d9c6f-594c-4106-9583-5e5a3c22d071_x-oss-process=image%2Fformat%2Cwebp.png

e.加了水印后效果如下图,但是会出现一个问题,就是视频在点击全屏时,水印会消失

e29234763f316f4c3960019d328e0bfa_1711626311241-12a736e7-8c6d-45c9-a358-7dd59b1f7e31_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png 全屏时水印消失:

63c8700f278edb8187d34767ae38dd4e_1711626341514-34cd5f44-27e7-41ac-ad23-2acd6cba238c_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png

f.处理全屏视频时水印消失的问题:

这段代码的意思主要是监听视频全屏时,就去拿到视频标签元素 和 水印标签元素,然后把 水印标签元素append到视频标签元素里面去就可以显示水印了。(因为我这里用的是腾讯云sdk,大家可以根据自己用的视频插件来写,基本逻辑就在这里了) 原因就是在视频全屏播放时,会把其他的元素都隐藏掉(css默认)。所以很多做视频开发的开发者,他们的全屏其实不是真正的全屏,而是套了一个壳,把外面的壳放大了。

// 用户全屏添加水印
      this.player.on('fullscreenchange', () => {
        const video_div = document.getElementsByClassName('course_video')[0]
        video_div.appendChild(document.getElementsByClassName('my_course_video_box')[0])
      })

60adb79bf36e26ffb0bcd80eb5055d33_1711627199045-92bf3f33-9d78-4f39-bd82-8fa1c1546184_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png

3.补充(水印指令的用法)

如果只想作用于一个盒子时出现了这个情况,那么你需要给水印盒子添加一个position: relative;属性

3e686de010061296bc44b4b456985c59_1711628943651-bceef94f-6900-4ba8-945e-3591bc7386a0_x-oss-process=image%2Fformat%2Cwebp.png 盒子css添加position: relative;属性

 .fanwai{
    width: 800px;
    height: 150px;
    border: 1px solid rebeccapurple;
    margin-top: 20px;
    position: relative;
  }

效果:

34611e0f80823df3281383ea78cc7807_1711629020901-3675c505-0a54-4f7f-8945-2f2c7efcfc1c_x-oss-process=image%2Fformat%2Cwebp.png

4.缺点:

该水印指令生成的水印 可以通过删除dom元素(如果你的水印是在一个单独的dom的话,如果你是作用在body上就不会,因为你把body删了里面的内容也没了)就把水印删了(只能说防普通用户,防君子)。可以找下其他的水印插件看看。 但是视频全屏时添加水印的逻辑是不变的。

5.demo地址:

github.com/rui-rui-an/…

如果demo运行起来视频不可用,可能是云点播的license过期了,大家可以自己去申请一个填到项目里。 云点播地址:cloud.tencent.com/document/pr…

5a475a9e65394caad11a094dbb3b2f70_1711900467731-c31f0ede-a325-4526-8d25-d40978f10a1e_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png 填到这里就可以了 5b6c3ed88485489b2615ad3c53e704c4_1711900516485-b6d73036-93f7-4774-9c8c-bead0a1fe78a_x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_984%2Climit_0.png

6.参考链接:

vue 指令实现水印效果(掘金):juejin.cn/post/696698…