Passed
Push — master ( 671d58...c8c24d )
by Amin
03:46
created

ffmpeg_streaming.media.Export.package()   B

Complexity

Conditions 5

Size

Total Lines 26
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 20
nop 10
dl 0
loc 26
rs 8.9332
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
"""
2
ffmpeg_streaming.media
3
~~~~~~~~~~~~
4
5
Media object to build a stream objects
6
7
8
:copyright: (c) 2019 by Amin Yazdanpanah.
9
:website: https://www.aminyazdanpanah.com
10
:email: [email protected]
11
:license: MIT, see LICENSE for more details.
12
"""
13
14
import os
15
import shutil
16
import tempfile
17
18
from ffmpeg_streaming.build_commands import build_command
19
from ffmpeg_streaming.clouds import open_from_cloud, save_to_clouds
20
from ffmpeg_streaming.export_hls_playlist import export_hls_playlist
21
from ffmpeg_streaming.utiles import get_path_info, clear_tmp_file, is_url
22
from .key_info_file import generate_key_info_file
23
from .process import Process
24
from ._ffprobe import *
25
from .auto_rep import AutoRepresentation
26
27
28
def _get_paths(output, _input, clouds):
29
    is_tmp = False
30
31
    if output is not None:
32
        dirname, name = get_path_info(output)
33
    else:
34
        dirname, name = get_path_info(_input)
35
        output = _input
36
    if clouds is not None:
37
        is_tmp = True
38
        basename = os.path.basename(output)
39
        output = os.path.join(tempfile.mkdtemp(suffix='ffmpeg_streaming'), basename)
40
        dirname, name = get_path_info(output)
41
42
    return output, dirname, name, is_tmp
43
44
45
def _save_hls_master_playlist(output, master_playlist_path, dirname, name):
46
    if is_url(output):
47
        if master_playlist_path is None:
48
            raise ValueError("You must specify a path for master playlist")
49
        playlist_path = master_playlist_path
50
        manifests = dirname + "/" + name
51
    else:
52
        playlist_path = dirname + "/" + name + ".m3u8"
53
        manifests = name
54
    export_hls_playlist(playlist_path, manifests, Export.reps)
55
56
57
class Export(object):
58
    video_format = str
59
    audio_format = str
60
    _ffprobe = dict
61
    reps = list
62
    output = str
63
    _is_tmp_directory = False
64
65
    def __init__(self, filename, options):
66
        self.filename = filename
67
        self.options = options
68
69
    def __del__(self):
70
        clear_tmp_file(self.filename)
71
        if isinstance(self, HLS):
72
            clear_tmp_file(self.hls_key_info_file)
73
        if Export._is_tmp_directory:
74
            shutil.rmtree(os.path.dirname(str(Export.output)), ignore_errors=True)
75
76
    def __getattr__(self, name):
77
        def method(*args, **kwargs):
78
            # TODO: implement save and live methods in the future
79
            if name in ['save', 'live']:
80
                self.package(*args, **kwargs)
81
            else:
82
                raise AttributeError("The object has no attribute {}".format(name))
83
84
        return method
85
86
    def add_rep(self, *args):
87
        Export.reps = list(args)
88
        return self
89
90
    def auto_rep(self, heights=None, cmd='ffprobe'):
91
        Export._ffprobe = ffprobe(self.filename, cmd)
92
        Export.reps = AutoRepresentation(Export._ffprobe, heights).generate()
93
        return self
94
95
    def format(self, video, audio=None):
96
        Export.video_format = video
97
        Export.audio_format = audio
98
        return self
99
100
    def package(
101
            self,
102
            output=None,
103
            clouds=None,
104
            progress=None,
105
            cmd='ffmpeg',
106
            c_stdout=False,
107
            c_stderr=True,
108
            c_stdin=True,
109
            c_input=None,
110
            timeout=None
111
         ):
112
        Export.output, dirname, name, Export._is_tmp_directory = _get_paths(output, self.filename, clouds)
113
114
        if isinstance(self, HLS):
115
            _save_hls_master_playlist(output, self.master_playlist_path, dirname, name)
116
117
        with Process(progress, build_command(cmd, self), c_stdout, c_stderr, c_stdin) as process:
118
            p = process.run(c_input, timeout)
119
120
        save_to_clouds(clouds, dirname)
121
122
        if output is not None and clouds is not None:
123
            shutil.move(dirname, os.path.dirname(output))
124
125
        return self, p, Export._ffprobe
126
127
128
class HLS(Export):
129
130
    def __init__(self, filename, **options):
131
        self.hls_time = options.pop('hls_time', 10)
132
        self.hls_allow_cache = options.pop('hls_allow_cache', 0)
133
        self.hls_list_size = options.pop('hls_list_size', 0)
134
        self.master_playlist_path = options.pop('master_playlist_path', 0)
135
        self.hls_key_info_file = options.pop('hls_key_info_file', None)
136
        super(HLS, self).__init__(filename, options)
137
138
    def encryption(self, url, path, length=16):
139
        self.hls_key_info_file = generate_key_info_file(url, path, length)
140
        return self
141
142
143
class DASH(Export):
144
145
    def __init__(self, filename, **options):
146
        self.adaption = options.pop('adaption', None)
147
        self.init_seg_name = options.pop('init_seg_name', None)
148
        self.media_seg_name = options.pop('media_seg_name', None)
149
        super(DASH, self).__init__(filename, options)
150
151
152
class StreamToFile(Export):
153
154
    def __init__(self, filename, **options):
155
        super(StreamToFile, self).__init__(filename, options)
156
157
158
def _check_file(file):
159
    if type(file) == tuple:
160
        file = open_from_cloud(file)
161
    return file
162
163
164
def dash(file, **options):
165
    return DASH(_check_file(file), **options)
166
167
168
def hls(file, **options):
169
    return HLS(_check_file(file), **options)
170
171
172
def stream2file(file, **options):
173
    return StreamToFile(file, **options)
174
175
176
__all__ = [
177
    'dash',
178
    'hls',
179
    'stream2file'
180
]
181