📜 ⬆️ ⬇️

Under the white flag post, or How I saved your video course from appearing on the tracker

captain_barbossa.jpg

Hi, Habr! Hmm, I have the feeling that we have already met ... Oh, yes. Here is the post where we discussed the lamp condition of whether it was acceptable to monitor the environment, limit the user to the number of devices to view, provide executable files instead of paid videos, and behave differently and uncivilized when organizing the “protection” of video courses from piracy.

And all would be nothing, but that's just not to criticize, not offering in return his decision. “You can do better, or what ?!” , - cries from comments were heard. “It would be better to support my compatriot, to help make their product better!” , I briefly retell some general thoughts. Fair. So, I really can do better . At the very least, my proposal will not require the end user to launch a curved software instead of the expected video files.

Solving all problems


And the solution is the most trivial, friends: watermarks. Yes, just watermarks. Instead of inventing complex binding mechanisms for a specific device, “sign” the video sequence. That’s all.

What properties should a watermark have in order to perform a defensive function:
')
  1. Watermark must contain information that uniquely identifies the user who bought the video course. This can be an activation key issued to the user, or a username obtained when registering on the video course purchase site, or time stamps corresponding to the course purchase time (of course, if you can unambiguously correlate them with the buyer's personality), or anything from this opera.
  2. Watermark should cover most of the frame so that it cannot be cut without major losses for the video course.
  3. The scheme of imposing a watermark should be random for each copy of the course, so that the villain does not write an automator on cutting out that same watermark.

If you make a watermark highly transparent, its presence does not interfere with the user, but still it is worth mentioning this in the course description before paying .

Thus, to extract incriminating information, a potential pirate would need to go through one of the scenarios described below:

  1. Cut the entire watermark (remember that according to the 2nd property, the watermark should occupy the entire screen and continue to perform its protective functions even if it is partially erased), thereby devaluing the video (in my opinion, it is logical that in the case where there is no roller, there is no value roller).
  2. Edit each frame separately to get rid of the watermark, without causing significant damage to the video. The complexity of performing such an action manually exceeds the creation of a video from scratch, and according to the 3rd property, the offender does not have the ability to automate the process.
  3. (?) Probably, you can ask a smart neural network to do it for you. Although not sure, not an expert, you can correct me in the comments.

Proof-of-concept


For half an hour, a trivial script of 100 lines was compiled, demonstrating the simplicity and accessibility of the implementation of such protection. I emphasize : not to show how clever I am, but quite the opposite, to note that a person very far from image processing could create quite working code (under the spoiler) in half an hour, like this:

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() 


The result of the script, on this sample as an example:

sample_original.gif

sample_signed.gif


Not for the sake of HYIP, but only for the common good.

I have the honor.

Source: https://habr.com/ru/post/450344/


All Articles