白标帖子,或“我如何保存您的视频课程,使其不出现在跟踪器上”

captain_barbossa.jpg

哈Ha! 嗯,我觉得我们已经见过面了...嗯,是的。 是我们在帖子中讨论了监视环境是否可接受,将用户限制为观看设备的数量,提供可执行文件而不是付费视频以及在组织视频课程“保护”免受盗版时以各种可能的方式表现的方式。

一切都会好起来的,但是如果没有提出解决方案的话,就无法批评。 “你能做得更好吗?” -听到评论的感叹。 “支持同胞会更好,帮助他们改善产品!” -我简短地讲了一些一般想法。 公平。 因此, 我确实可以做得更好 。 至少,我的建议不会要求最终用户运行弯曲的软件而不是预期的视频文件。

解决所有问题


解决方案是最简单的朋友:水印。 是的,只是水印。 与其提出用于绑定到特定设备的复杂机制,不如对视频序列进行“签名”。 仅此而已。

水印应具有哪些属性才能执行防御功能:

  1. 水印应包含唯一标识购买视频课程的用户的信息。 这可以是发给用户的激活密钥,也可以是在视频课程购买网站上注册后获得的用户登录信息,或者是与课程购买时间相对应的时间戳记(当然,如果您可以明确地将他们与购买者的身份相关联),或者是该歌剧中的任何内容。
  2. 水印应覆盖帧的大部分,以便在视频过程中不会造成重大损失的情况下将其切掉。
  3. 水印叠加方案对于课程的每个副本都应该是随机的,以便反派不会编写自动机器来切出相同的水印。

如果使水印非常透明,则水印的存在不会干扰用户,但是仍然值得在付款前的课程说明中提及。

因此,为了提取揭露的信息,潜在的海盗将需要遵循以下情况之一:

  1. 切掉整个水印(请记住,根据第二个属性,水印应占据整个屏幕,即使被部分擦除也应继续执行其保护功能),从而使视频片段无效(我认为在没有太多水印的情况下是合乎逻辑的视频,没有任何价值)。
  2. 单独编辑每个帧以消除水印,而不会对视频造成重大损害。 手动执行此类操作的复杂性超过了从头开始创建视频的复杂度,并且根据第3个属性,入侵者无法自动执行该过程。
  3. (?)我猜您可以要求一个智能神经网络来为您执行此操作。 尽管不确定(不是专家),但您可以在评论中纠正我。

概念证明


在半小时内,编写了一个包含100行的琐碎脚本,证明了实现这种保护的简单性和可访问性。 我强调 :并不是要展示我的聪明,而是要相反,要指出一个非常远离图像处理的人能够在半小时内编写一个完整的工作代码(在扰流器下),这很简单:

fckInfoprotectorV2.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Usage: python3 fckInfoprotectorV2.py import os from shutil import rmtree import numpy as np import cv2 class VideoSigner: def __init__(self, video, watermark): os.makedirs('original') os.makedirs('watermarked') self.vidin = cv2.VideoCapture(video) self.fps = self.vidin.get(cv2.CAP_PROP_FPS) self.frame_size = ( int(self.vidin.get(cv2.CAP_PROP_FRAME_WIDTH)), int(self.vidin.get(cv2.CAP_PROP_FRAME_HEIGHT)) ) self.watermark = cv2.imread(watermark, cv2.IMREAD_UNCHANGED) self.wH, self.wW = self.watermark.shape[:2] B, G, R, A = cv2.split(self.watermark) B = cv2.bitwise_and(B, B, mask=A) G = cv2.bitwise_and(G, G, mask=A) R = cv2.bitwise_and(R, R, mask=A) self.watermark = cv2.merge([B, G, R, A]) def __del__(self): rmtree('original') rmtree('watermarked') def _split(self): print('[*] Splitting video by frames... ', end='', flush=True) (success, image), count = self.vidin.read(), 0 while success: path = os.path.join('original', f'{count}.jpg') cv2.imwrite(path, image) success, image = self.vidin.read() count += 1 print('Done') def _watermark(self): print('[*] Signing each frame... ', end='', flush=True) for image_name in sorted( os.listdir('original'), key=lambda x: int(x.split('.')[0]) ): image_path = os.path.join('original', image_name) image = cv2.imread(image_path) h, w = image.shape[:2] image = np.dstack([ image, np.ones((h, w), dtype='uint8') * 255 ]) overlay = np.zeros((h, w, 4), dtype='uint8') half_h_diff = (h - self.wH) // 2 half_w_diff = (w - self.wW) // 2 overlay[half_h_diff:half_h_diff + self.wH, half_w_diff:half_w_diff + self.wW] = self.watermark output = image.copy() cv2.addWeighted(overlay, 0.25, output, 1.0, 0, output) path = os.path.join('watermarked', image_name) cv2.imwrite(path, output) print('Done') def _merge(self): print('[*] Merging signed frames... ', end='', flush=True) self.vidout = cv2.VideoWriter( 'signed.avi', cv2.VideoWriter_fourcc(*'XVID'), fps=self.fps, frameSize=self.frame_size ) for image_name in sorted( os.listdir('watermarked'), key=lambda x: int(x.split('.')[0]) ): image_path = os.path.join('watermarked', image_name) image = cv2.imread(image_path) self.vidout.write(image) print('Done') def sign(self): self._split() self._watermark() self._merge() if __name__ == '__main__': signer = VideoSigner('SampleVideo_1280x720_1mb.mp4', 'watermark.png') signer.sign() 


脚本的结果,以示例为例:

sample_original.gif

sample_signed.gif


不是为了大肆宣传,而是为了共同的利益。

我很荣幸

Source: https://habr.com/ru/post/zh-CN450344/


All Articles