1 | """ |
||
2 | ffmpeg_streaming.media |
||
3 | ~~~~~~~~~~~~ |
||
4 | |||
5 | Video and audio formats |
||
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 abc |
||
14 | |||
15 | |||
16 | MULTIPLY_BY_ONE = 1 |
||
17 | MULTIPLY_BY_TWO = 2 |
||
18 | MULTIPLY_BY_FOUR = 4 |
||
19 | MULTIPLY_BY_Eight = 8 |
||
20 | MULTIPLY_BY_SIXTEEN = 16 |
||
21 | MULTIPLY_BY_THIRTY_TWO = 32 |
||
22 | |||
23 | |||
24 | def _verify_codecs(codec, codecs): |
||
25 | if codec is None: |
||
26 | return |
||
27 | elif codec not in codecs: |
||
28 | ValueError("The codec is not available!") |
||
29 | else: |
||
30 | return str(codec) |
||
31 | |||
32 | |||
33 | class Format(abc.ABC): |
||
34 | """ |
||
35 | @TODO: add documentation |
||
36 | """ |
||
37 | def __init__(self, video: str, audio: str, **codec_options): |
||
38 | self.video = video |
||
39 | self.audio = audio |
||
40 | self.codec_options = codec_options |
||
41 | |||
42 | @property |
||
43 | def all(self) -> dict: |
||
44 | args = { |
||
45 | 'c:v': self.video, |
||
46 | 'c:a': self.audio, |
||
47 | } |
||
48 | args.update(self.get_codec_options()) |
||
49 | |||
50 | return args |
||
51 | |||
52 | @abc.abstractmethod |
||
53 | def multiply(self) -> int: |
||
54 | pass |
||
55 | |||
56 | @abc.abstractmethod |
||
57 | def get_codec_options(self) -> dict: |
||
58 | pass |
||
59 | |||
60 | |||
61 | View Code Duplication | class H264(Format): |
|
0 ignored issues
–
show
Duplication
introduced
by
Loading history...
|
|||
62 | def __init__(self, video: str = "libx264", audio: str = 'aac', **codec_options): |
||
63 | """ |
||
64 | @TODO: add documentation |
||
65 | """ |
||
66 | videos = ['libx264', 'h264', 'h264_afm'] |
||
67 | audios = ['copy', 'aac', 'libvo_aacenc', 'libfaac', 'libmp3lame', 'libfdk_aac'] |
||
68 | |||
69 | super(H264, self).__init__(_verify_codecs(video, videos), _verify_codecs(audio, audios), **codec_options) |
||
70 | |||
71 | def multiply(self) -> int: |
||
72 | return MULTIPLY_BY_TWO |
||
73 | |||
74 | def get_codec_options(self) -> dict: |
||
75 | """ |
||
76 | set the default value of h264 codec options and update the value with the specified value by user |
||
77 | see https://ffmpeg.org/ffmpeg-codecs.html#Options-28 for more information about options |
||
78 | :return: dict |
||
79 | """ |
||
80 | h264_codec_options = { |
||
81 | 'bf': 1, |
||
82 | 'keyint_min': 25, |
||
83 | 'g': 250, |
||
84 | 'sc_threshold': 40 |
||
85 | } |
||
86 | |||
87 | h264_codec_options.update(self.codec_options) |
||
88 | |||
89 | return h264_codec_options |
||
90 | |||
91 | |||
92 | View Code Duplication | class HEVC(Format): |
|
0 ignored issues
–
show
|
|||
93 | """ |
||
94 | @TODO: add documentation |
||
95 | """ |
||
96 | def __init__(self, video: str = "libx265", audio: str = 'aac', **codec_options): |
||
97 | videos = ['libx265', 'h265'] |
||
98 | audios = ['copy', 'aac', 'libvo_aacenc', 'libfaac', 'libmp3lame', 'libfdk_aac'] |
||
99 | |||
100 | super(HEVC, self).__init__(_verify_codecs(video, videos), _verify_codecs(audio, audios), **codec_options) |
||
101 | |||
102 | def multiply(self) -> int: |
||
103 | return MULTIPLY_BY_TWO |
||
104 | |||
105 | def get_codec_options(self) -> dict: |
||
106 | """ |
||
107 | set the default value of hevc(h265) codec options and update the value with the specified value by user |
||
108 | see https://ffmpeg.org/ffmpeg-codecs.html#Options-29 for more information about options |
||
109 | :return: dict |
||
110 | """ |
||
111 | h265_codec_options = { |
||
112 | 'keyint_min': 25, |
||
113 | 'g': 250, |
||
114 | 'sc_threshold': 40 |
||
115 | } |
||
116 | |||
117 | h265_codec_options.update(self.codec_options) |
||
118 | |||
119 | return h265_codec_options |
||
120 | |||
121 | |||
122 | class VP9(Format): |
||
123 | """ |
||
124 | @TODO: add documentation |
||
125 | """ |
||
126 | def __init__(self, video: str = "libvpx-vp9", audio: str = 'aac', **codec_options): |
||
127 | videos = ['libvpx', 'libvpx-vp9'] |
||
128 | audios = ['copy', 'aac', 'libvo_aacenc', 'libfaac', 'libmp3lame', 'libfdk_aac'] |
||
129 | |||
130 | super(VP9, self).__init__(_verify_codecs(video, videos), _verify_codecs(audio, audios), **codec_options) |
||
131 | |||
132 | def multiply(self) -> int: |
||
133 | return MULTIPLY_BY_TWO |
||
134 | |||
135 | def get_codec_options(self) -> dict: |
||
136 | """ |
||
137 | set the default value of hevc(h265) codec options and update the value with the specified value by user |
||
138 | see https://ffmpeg.org/ffmpeg-codecs.html#Options-26 for more information about options |
||
139 | :return: dict |
||
140 | """ |
||
141 | vp9_codec_options = {} |
||
142 | |||
143 | vp9_codec_options.update(self.codec_options) |
||
144 | |||
145 | return vp9_codec_options |
||
146 | |||
147 | |||
148 | class Formats: |
||
149 | @staticmethod |
||
150 | def h264(video: str = "libx264", audio: str = 'aac', **codec_options) -> Format: |
||
151 | """ |
||
152 | @TODO: add documentation |
||
153 | """ |
||
154 | return H264(video, audio, **codec_options) |
||
155 | |||
156 | @staticmethod |
||
157 | def hevc(video: str = "libx265", audio: str = 'aac', **codec_options) -> Format: |
||
158 | """ |
||
159 | @TODO: add documentation |
||
160 | """ |
||
161 | return HEVC(video, audio, **codec_options) |
||
162 | |||
163 | @staticmethod |
||
164 | def vp9(video: str = "libvpx-vp9", audio: str = 'aac', **codec_options) -> Format: |
||
165 | """ |
||
166 | @TODO: add documentation |
||
167 | """ |
||
168 | return VP9(video, audio, **codec_options) |
||
169 | |||
170 | |||
171 | __all__ = [ |
||
172 | 'Format', |
||
173 | 'Formats' |
||
174 | ] |
||
175 |