Passed
Pull Request — master (#74)
by
unknown
03:17 queued 02:13
created

ffmpeg_streaming._input.Input.__getattr__()   A

Complexity

Conditions 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 2
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
"""
2
ffmpeg_streaming.input
3
~~~~~~~~~~~~
4
5
Input options
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
from ffmpeg_streaming._media import Media
14
from ffmpeg_streaming._utiles import get_os, cnv_options_to_args
15
from ffmpeg_streaming._clouds import Clouds
16
17
cloud = None
18
19
20
class Capture(object):
21
    def __init__(self, video, options):
22
        """
23
        @TODO: add documentation
24
        """
25
        self.options = options
26
        self.video = video
27
28
    def _linux(self):
29
        cap = 'x11grab' if (is_screen := self.options.pop('screen', False)) else 'v4l2'
30
        return {
31
            'f': cap,
32
            'i': self.video
33
        }
34
35
    def _windows(self):
36
        self.video = 'video=' + str(self.video)
37
        windows_audio = self.options.pop('windows_audio', None)
38
        if windows_audio is not None:
39
            self.video = f'{self.video}:audio=' + str(windows_audio)
40
41
        return {
42
            'f': 'dshow',
43
            'i': self.video
44
        }
45
46
    def _os_x(self):
47
        return {
48
            'f': 'avfoundation',
49
            'i': self.video
50
        }
51
52
    @staticmethod
53
    def _unknown():
54
        raise OSError("Unreported OS!")
55
56
    def __iter__(self):
57
        yield from getattr(self, '_' + get_os())().items()
58
59
60
def get_from_cloud(_cloud: Clouds, options: dict):
61
    """
62
    @TODO: add documentation
63
    """
64
    global cloud
65
    if cloud is None:
66
        save_to = options.pop('save_to', None)
67
        cloud = {'i': _cloud.download(save_to, **options), 'is_tmp': save_to is None}
68
69
    return cloud
70
71
72
class InputOption(object):
73
    def __init__(self, _input, **options):
74
        """
75
        @TODO: add documentation
76
        """
77
        self.input_ = _input
78
        self.options = options
79
80
    def __str__(self):
81
        """
82
        @TODO: add documentation
83
        """
84
        return " ".join(cnv_options_to_args(self._create()))
85
86
    def __iter__(self):
87
        """
88
        @TODO: add documentation
89
        """
90
        yield from self._create().items()
91
92
    def _create(self):
93
        """
94
        @TODO: add documentation
95
        """
96
        options = self.options.pop('pre_opts', {'y': None})
97
        is_cap = self.options.pop('capture', False)
98
99
        if isinstance(self.input_, Clouds):
100
            options.update(get_from_cloud(self.input_, self.options))
101
        elif is_cap:
102
            options.update(Capture(self.input_, self.options))
103
        elif isinstance(self.input_, (str, int)):
104
            i_options = {'i': str(self.input_)}
105
            i_options.update(self.options)
106
            options.update(i_options)
107
        else:
108
            raise ValueError("Unknown input!")
109
110
        return options
111
112
113
class Input:
114
    def __init__(self, _input: InputOption):
115
        """
116
        @TODO: add documentation
117
        """
118
        self.inputs = [_input]
119
120
    def input(self, _input, **options):
121
        """
122
        @TODO: add documentation
123
        """
124
        self.inputs.append(InputOption(_input, **options))
125
126
    def __getattr__(self, name):
127
        """
128
        @TODO: add documentation
129
        """
130
        def method(*args, **kwargs):
131
            media = Media(self)
132
            if hasattr(media, name):
133
                return getattr(media, name)(*args, **kwargs)
134
            else:
135
                raise AttributeError("The object has no attribute {}".format(name))
136
137
        return method
138
139
140
def input(_input, **options) -> Input:
141
    """Input options (ffmpeg pre_option ``-i`` input options)
142
        You can also pass a cloud object as an input to the method. the file will be downloaded and will pass it to ffmpeg
143
        if you want to open a resource from a pipe, set input "pipe:"
144
        if you want to open a resource from a capture device, pass a device name as filename and set the capture keyword
145
        to True. To list the supported, connected capture devices, see https://trac.ffmpeg.org/wiki/Capture/Webcam
146
         and https://trac.ffmpeg.org/wiki/Capture/Desktop. See https://ffmpeg.org/ffmpeg.html#Main-options and
147
         https://ffmpeg.org/ffmpeg-protocols.html for more information about input option and supported resources
148
         such as http, ftp, and so on.
149
        """
150
    return Input(InputOption(_input, **options))
151
152
153
__all__ = [
154
    'input',
155
]
156