Passed
Push — master ( 7bc1c2...5b857f )
by Amin
03:31
created

HLSKeyInfoFile.generate()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
"""
2
ffmpeg_streaming.media
3
~~~~~~~~~~~~
4
5
HLS helper
6
7
8
:copyright: (c) 2020 by Amin Yazdanpanah.
9
:website: https://www.aminyazdanpanah.com
10
:email: [email protected]
11
:license: MIT, see LICENSE for more details.
12
"""
13
import os
14
import uuid
15
from secrets import token_bytes, token_hex
16
17
from ffmpeg_streaming._utiles import mkdir
18
19
20
class HLSKeyInfoFile:
21
    def __init__(self, key_info_file_path: str, path: str, url: str, period: int = 0, needle: str = '', length: int = 16):
22
        self.needle = needle
23
        self.period = period
24
        self.segments = []
25
        self.length = length
26
        self.url = self.c_url = url
27
        self.path = self.c_path = path
28
        mkdir(os.path.dirname(path))
29
        self.key_info_file_path = key_info_file_path
30
31
    def __str__(self):
32
        self.generate()
33
        return self.key_info_file_path
34
35
    def generate(self):
36
        self.generate_key()
37
        self.update_key_info_file()
38
39
    def generate_key(self):
40
        with open(self.path, 'wb') as key:
41
            key.write(token_bytes(self.length))
42
43
    def update_key_info_file(self):
44
        with open(self.key_info_file_path, 'w') as key_info_file:
45
            key_info_file.write("\n".join([self.url, self.path, token_hex(self.length)]))
46
47
    def update_suffix(self):
48
        unique = uuid.uuid4()
49
        self.path = self.c_path + "-" + str(unique)
50
        self.url = self.c_url + "-" + str(unique)
51
52
    def rotate_key(self, line: str):
53
        if self.needle in line and line not in self.segments:
54
            self.segments.append(line)
55
            if len(self.segments) % self.period == 0:
56
                self.update_suffix()
57
                self.generate()
58
59
60
def stream_info(rep) -> list:
61
    # @TODO: add custom stream info
62
    tag = '#EXT-X-STREAM-INF:'
63
    info = [
64
        'BANDWIDTH=' + str(rep.bitrate.normalize_video(False)),
65
        'RESOLUTION=' + rep.size.normalize,
66
        'NAME="' + str(rep.size.height) + '"'
67
    ]
68
    
69
    return [tag + ",".join(info)]
70
71
72
class HLSMasterPlaylist:
73
    def __init__(self, media):
74
        self.media = media
75
        self.path = media.output
76
77
    @classmethod
78
    def generate(cls, media):
79
        path = os.path.join(os.path.dirname(media.output_), os.path.basename(media.output_).split('.')[0] + '.m3u8')
80
        with open(path, 'w', encoding='utf-8') as playlist:
81
            playlist.write(cls(media)._content())
82
83
    def _content(self) -> str:
84
        content = ['#EXTM3U'] + self._get_version() + self.media.options.get('description', [])
85
86
        for rep in self.media.reps:
87
            content += stream_info(rep) + self.stream_path(rep)
88
89
        return "\n".join(content)
90
91
    def _get_version(self) -> list:
92
        version = "7" if hasattr(self.media, 'fragmented_mp4') else "3"
93
        return ['#EXT-X-VERSION:' + version]
94
95
    def stream_path(self, rep):
96
        return [str(os.path.basename(self.media.output_).split('.')[0]) + "_" + str(rep.size.height) + "p.m3u8"]
97