2014-09-11 3 views
2

J'ai mis en place un site de vidéo qui sert des fichiers m3u8 et des fichiers ts associés pour les utilisateurs. Je ne veux pas que les fichiers multimédias soient disponibles gratuitement, donc ce que j'ai fait c'est: quand l'utilisateur est sur le site, une session est créée dans mysql avec son IP et un token; Lorsqu'ils demandent un fichier dans le sous-domaine média spécifique (mp4.domain.com), le module d'authentification Nginx interroge localhost: 8080 avec l'url et le jeton joint en tant que cookie de requête défini via javascript ... interroge la base de données et autorise/refuse l'accès au fichier dépend des informations de session. Maintenant, cela fonctionne très bien, le temps système est compris entre 8 et 20 MS en fonction de la charge du serveur et il n'est pas nécessaire de manipuler les URL en PHP lors de la génération du lien m3u8; OSMF obtient juste le m3u8 et demande les fichiers, javascript ajoute le cookie de jeton et Bob votre oncle.URL enregistrée dans Google Cloud Storage pour les médias

Maintenant, nous migrons vers Google Cloud Storage et le problème auquel je suis confronté est que je ne peux pas vraiment contrôler tout cela ... une URL signée pour le m3u8 est assez facile, mais chaque m3u8 Devrait être généré dynamiquement avec des urls signés pour chaque fichier ts pour chaque résolution, vignette et audio aac (pour vous donner une idée, une vidéo aléatoire que j'ai choisi a 1.043 fichiers au total) ... ce qui fait 1.043 différentes URL signées à générer, à environ 6 MS chacun donne 6 secondes de temps de génération totale ... ce qui est horrible.

Existe-t-il une autre façon de gérer cela? Je ne suis pas très friand de l'API Cloud Storage, mais je n'arrive pas à trouver autre chose ... Les listes de contrôle d'accès semblent inutiles et la seule autre chose à laquelle je peux penser est la rotation des emplacements de ... ? ... base afin de les obfusciter. Est-ce que quelqu'un a eu une situation similaire ou a une idée de l'endroit où je peux commencer à jouer pour résoudre ce problème?

+0

Y a-t-il une petite liste de m3u8 auxquels de nombreux utilisateurs ont accès? Une option pourrait être de générer un nouveau m3u8 de manière asynchrone, puis de le servir pendant les prochaines heures avant de générer un nouveau. Cela pourrait ne pas fonctionner s'il y a des millions de m3u8 distincts. –

+0

@BrandonYarbrough; à ce jour, il y a 678 vidéos au total sur le site (ce qui équivaut à 4 068 m3u8s [un pour chacun des 180 360 602 720, 1080 AAC]). Bien que vous posiez une bonne idée ... je pourrais écrire un script qui génère toutes les m3u8s toutes les x heures, poster cela au dB et tirer de là en générant uris pour le joueur ... une solution réalisable ... Je suis aller jouer avec ça et voir ce que je reçois. – hdezela

Répondre

2

Après plus de recherche, je suis venu à la conclusion suivante:

Mes premiers calculs lorsqu'ils sont effectués en utilisant l'outil de gsutil de Google, qui semble présenter beaucoup de frais généraux lors du calcul d'un hachage URL signé, par exemple:

code gsutil:

gsutil signurl -d 60m /path/to/google.p12 gs://bucket/file 

temps d'exécution: 0,73812007904053

, cependant, en utilisant des fonctions PHP natives pour cre mangé une URL signé est beaucoup plus rapide:

Code PHP:

function storageURL($bucket,$archivo) { 
    $expires = time()+60; 
    $to_sign = ("GET\n\n\n".$expires."\n/".$bucket.'/'.$archivo); 
    $fp = fopen('/path/to/google.pem', 'r'); 
    $priv_key = fread($fp, 8192); 
    fclose($fp); 
    $pkeyid = openssl_get_privatekey($priv_key); 
    if(!openssl_sign($to_sign,$signature,$pkeyid,'sha256')) { 
     $signature = 'sinfirma'; 
    } else { 
     $signature = urlencode(base64_encode($signature)); 
    } 
    return ('https://'.$bucket.'.storage.googleapis.com/'.$archivo.'[email protected]&Expires='.$expires.'&Signature='.$signature); 
} 

Temps d'exécution: ,0007929801940918

Cela change tout, en cours d'exécution 2000 itérations du code PHP me donne encore qu'un temps d'exécution de 1.0643119812012 plus 0,0325711573357 supplémentaire pour la création de tous les fichiers m3u8 plus 0.0039050579071045 pour 6 itérations supplémentaires pour créer les URL signées pour les m3u8s; donnant un temps d'exécution total de 1.100788196444004 secondes, la plus grande partie dépendant de la longueur de la vidéo. Cela semble vraiment bien, car les utilisateurs sont habitués à des durées de "chargement" ou de "mise en mémoire tampon" plus longues pour les vidéos plus longues, de sorte que les ~ 0.5 - ~ 1.5 secondes supplémentaires lorsque la vidéo est plus longue n'affecteront pas vraiment la convivialité. En passant, dans l'état actuel, il y a actuellement 689 vidéos sur le serveur, avec un total de 864138 fichiers .ts et .aac liés, chaque vidéo ayant 6 m3u8s (180,360,480,720,1080, AAC) plus un m3u8 pour la playlist principale ... donc générer une url horaire pour toutes les vidéos nécessiterait (689 [master m3u8] + 864 138 [assets] + 4134 [qual m3u8]) 868 961 itérations du code PHP, soit une durée totale de 467.15262699127 (~ 7 minutes), ce qui est gérable mais discutable compte tenu du temps d'exécution pour générer dynamiquement chaque URL. Tout ceci utilise une instance de Google Compute n1-highmem-2, qui n'est pas très puissante, donc passer à une machine plus puissante rendra tout cela encore plus rapide. Mais tout cela apporte une autre dimension dans le pli, comme Google (comme tous les autres le font) charge par opération PUT sur chaque seau, donc un calcul des coûts est en ordre. En regardant nos statistiques pour le mois dernier, je vois un total de 447.103 jeux vidéo au total (hé, c'est un petit site), qui, selon le schéma proposé, aurait généré 7 opérations PUT pour chaque hit vidéo (6 bitrate m3u8 + 1 master m3u8), un total de 3.129.721 PUT supplémentaires ce mois-ci, calculant pour le coût (3129721/10000 * 0.01) me donne un chiffre de 3,13 $ de coût supplémentaire pour ce ... petit mais pourrait devenir un problème si le site devient plus populaire. L'autre solution (URL signées à l'heure pour tout le monde) générerait ((689 [maître m3u8] + 4134 [qual m3u8]) * 24 [gens par jour] * 30 [jours par mois]) 3 472 560 PUT supplémentaires ... ce qui est grosso modo la même chose, donc je suis à ou près du seuil de rentabilité (coût-sage) pour choisir entre les deux régimes. Je dois faire plus de chiffres ici en utilisant les données des mois précédents pour avoir une meilleure idée car un schéma (URL par hit) dépend du nombre d'utilisateurs et l'autre (génération d'URL globale) dépend de la quantité de vidéos ... et ils évoluent chacun de manière totalement différente. En gros, en utilisant du code natif, le problème semble être purement monétaire avec un petit vecteur de codage (réécriture du code de lecture vidéo par opposition à la génération d'une URL horaire). Les deux doivent être examinés et comparés avant de prendre une décision finale. Cependant, une nouvelle liste de contrôle d'accès dans l'API Cloud Storage (disons fichier multimédia avec m3u8 comme charge utile) pouvant être liée à un m3u8 rendrait tout plus facile à résoudre ... y a-t-il un endroit que je pourrais proposer? ceci à l'équipe de Google Storage?

- 30/10 Edit: Solution finale -

C'est la solution finale, je suis venu avec, et il semble fonctionner très bien jusqu'à présent.

Configuration:

Nginx sur Google Cloud Compute instance - m3u8.domain.com

  • Le convertisseur vidéo effectue les opérations suivantes: ffmpeg pour convertir 1.- fichiers source à 180,360,480,720,1080, Sous-dossiers AAC 2.- ffmpeg segmente les fichiers en 11 morceaux (moins de fichiers, iOS les accepte toujours) 3.- PHP copie tous les fichiers média dans le seau GS 4.- PHP analyse les fichiers m3u8 générés et crée une dynamique fichier m3u8 5.- PHP Les fichiers de copies et fichier master.m3u8 à répertoire approprié sur le disque dur attaché

  • Nouveau bloc serveur nginx.conf qui parse .m3u8 fichiers PHP en tant que joueur OSMF demandes 1.- maître m3u8, JS ajoute jeton de session PHP chèques 2.- jeton de session + IP pour valider l'utilisateur Si elle est validée 3.-, echos m3u8 vidéo actuelle 4.- Si non validée, echos m3u8 dire que vous n'êtes pas autorisé à voir cette vidéo

Le processus, pour un fichier vidéo 2:44:08 prend entre 0,7 - 0,9 secondes, presque invisible pour les utilisateurs. Pour les vidéos plus courtes, il est exponentiellement minuscule.

Seau de stockage Cloud (mp4domain) - mp4.domain.com

Le bucket a une liste de contrôle d'accès par défaut appliquée qui rend tous les fichiers privés mais accessibles à l'ID Google utilisé pour générer les URL signées.

Ainsi, une seule vidéo a les fichiers suivants:

SERVER/nginx/mp4/uniqid/uniqid.m3u8 
SERVER/nginx/mp4/uniqid/180p/stream.m3u8 
SERVER/nginx/mp4/uniqid/360p/stream.m3u8 
SERVER/nginx/mp4/uniqid/480p/stream.m3u8 
SERVER/nginx/mp4/uniqid/720p/stream.m3u8 
SERVER/nginx/mp4/uniqid/1080p/stream.m3u8 
SERVER/nginx/mp4/uniqid/audio/stream.m3u8 

GS/bucketmp4/uniqid/180p/segment##.ts 
GS/bucketmp4/uniqid/360p/segment##.ts 
GS/bucketmp4/uniqid/480p/segment##.ts 
GS/bucketmp4/uniqid/720p/segment##.ts 
GS/bucketmp4/uniqid/1080p/segment##.ts 
GS/bucketmp4/uniqid/audio/segment##.aac 

(SO Semble penser que c'est le code et ne me laisse pas formater autrement)

De cette façon, écrit à GS sont Une seule fois, et puisque tous les clients pensent recevoir des fichiers m3u8, aucun piratage ne doit être effectué côté client.

Espérons que cela peut aider quelqu'un avec des problèmes similaires.

Questions connexes