Ein Beitrag mit weißer Flagge oder Wie ich Ihren Videokurs vor dem Erscheinen auf dem Tracker gespeichert habe

Captain_barbossa.jpg

Hallo Habr! Hmm, ich habe das Gefühl, wir haben uns schon getroffen ... Ah, ja. In diesem Beitrag haben wir ausführlich diskutiert, ob es akzeptabel ist, die Umgebung zu überwachen, den Benutzer auf die Anzahl der anzuzeigenden Geräte zu beschränken, ausführbare Dateien anstelle von bezahlten Videos bereitzustellen und sich bei der Organisation des "Schutzes" von Videokursen vor Piraterie in jeder Hinsicht anders zu verhalten.

Und alles wäre in Ordnung, aber es ist einfach unmöglich zu kritisieren, ohne dafür eine Lösung vorzuschlagen. "Kannst du es besser machen?" - Ausrufe aus den Kommentaren wurden gehört. "Es wäre besser, einen Landsmann zu unterstützen und dabei zu helfen, sein Produkt besser zu machen!" - Ich erzähle kurz einige allgemeine Gedanken. Fair. Also kann ich es wirklich besser machen . Zumindest wird mein Vorschlag nicht erfordern, dass der Endbenutzer krumme Software anstelle der erwarteten Videodateien ausführt.

Lösung für alle Probleme


Und die Lösung ist die trivialste, Freunde: Wasserzeichen. Ja, nur Wasserzeichen. Anstatt komplexe Mechanismen für die Bindung an ein bestimmtes Gerät zu entwickeln, „signieren“ Sie die Videosequenz. Das ist alles

Welche Eigenschaften sollte ein Wasserzeichen haben, um eine Verteidigungsfunktion zu erfüllen:

  1. Das Wasserzeichen sollte Informationen enthalten, die den Benutzer, der den Videokurs gekauft hat, eindeutig identifizieren. Dies kann ein Aktivierungsschlüssel sein, der an den Benutzer ausgegeben wird, oder das Login des Benutzers, das bei der Registrierung auf der Kaufwebsite des Videokurses erhalten wurde, oder Zeitstempel, die dem Zeitpunkt des Kaufs des Kurses entsprechen (natürlich, wenn Sie sie eindeutig mit der Identität des Käufers korrelieren können), oder irgendetwas aus dieser Oper.
  2. Das Wasserzeichen sollte den größten Teil des Rahmens bedecken, damit es nicht ohne größere Verluste für den Videokurs ausgeschnitten werden kann.
  3. Das Wasserzeichen-Overlay-Schema sollte für jede Kopie des Kurses zufällig sein, damit der Bösewicht keine automatische Maschine zum Ausschneiden desselben Wasserzeichens schreibt.

Wenn Sie das Wasserzeichen sehr transparent machen, stört seine Anwesenheit den Benutzer nicht, aber es ist dennoch erwähnenswert, dies in der Kursbeschreibung vor der Zahlung zu erwähnen.

Um aufschlussreiche Informationen zu extrahieren, müsste ein potenzieller Pirat einem der unten beschriebenen Szenarien folgen:

  1. Schneiden Sie das gesamte Wasserzeichen aus (denken Sie daran, dass das Wasserzeichen gemäß der zweiten Eigenschaft den gesamten Bildschirm einnehmen und seine Schutzfunktionen auch dann ausführen sollte, wenn es teilweise gelöscht wird), wodurch der Videoclip ungültig wird (meiner Meinung nach ist es logisch, dass in dem Fall, in dem es nicht die meisten gibt Video gibt es keinen Videowert).
  2. Bearbeiten Sie jedes Bild einzeln, um das Wasserzeichen zu entfernen, ohne das Video erheblich zu beschädigen. Die Komplexität der manuellen Ausführung einer solchen Aktion übersteigt die Erstellung eines Videos von Grund auf neu, und gemäß der dritten Eigenschaft hat der Eindringling keine Möglichkeit, den Prozess zu automatisieren.
  3. (?) Ich denke, Sie können ein intelligentes neuronales Netzwerk bitten, dies für Sie zu tun. Obwohl nicht sicher, kein Spezialist, können Sie mich in den Kommentaren korrigieren.

Proof of Concept


In einer halben Stunde wurde ein triviales Skript mit 100 Zeilen erstellt, das die Einfachheit und Zugänglichkeit der Implementierung eines solchen Schutzes demonstriert. Ich betone : Um nicht zu zeigen, wie schlau ich bin, sondern im Gegenteil, um festzustellen, dass eine Person, die weit von der Bildverarbeitung entfernt ist, in einer halben Stunde einen voll funktionsfähigen Code (unter dem Spoiler) erstellen konnte, ist dies so einfach:

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


Das Ergebnis des Skripts in diesem Beispiel als Beispiel:

sample_original.gif

sample_signed.gif


Nicht für Hype, sondern nur für das Gemeinwohl.

Ich habe die Ehre.

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


All Articles