StreamingCommunity 1.7.6__py3-none-any.whl → 1.9.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of StreamingCommunity might be problematic. Click here for more details.

Files changed (101) hide show
  1. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/js_parser.py +4 -1
  2. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/util.py +166 -166
  3. StreamingCommunity/{Src/Api → Api}/Player/ddl.py +89 -89
  4. StreamingCommunity/{Src/Api → Api}/Player/maxstream.py +151 -151
  5. StreamingCommunity/{Src/Api → Api}/Player/supervideo.py +193 -193
  6. StreamingCommunity/{Src/Api → Api}/Player/vixcloud.py +224 -212
  7. StreamingCommunity/{Src/Api → Api}/Site/1337xx/__init__.py +50 -50
  8. StreamingCommunity/{Src/Api → Api}/Site/1337xx/costant.py +15 -15
  9. StreamingCommunity/{Src/Api → Api}/Site/1337xx/site.py +83 -83
  10. StreamingCommunity/{Src/Api → Api}/Site/1337xx/title.py +66 -66
  11. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/__init__.py +50 -50
  12. StreamingCommunity/{Src/Api/Site/mostraguarda → Api/Site/altadefinizione}/costant.py +15 -15
  13. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/film.py +69 -69
  14. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/site.py +86 -86
  15. StreamingCommunity/{Src/Api → Api}/Site/animeunity/__init__.py +50 -50
  16. StreamingCommunity/{Src/Api/Site/altadefinizione → Api/Site/animeunity}/costant.py +15 -15
  17. StreamingCommunity/{Src/Api → Api}/Site/animeunity/film_serie.py +130 -131
  18. StreamingCommunity/{Src/Api → Api}/Site/animeunity/site.py +164 -164
  19. StreamingCommunity/{Src/Api → Api}/Site/animeunity/util/ScrapeSerie.py +3 -3
  20. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/__init__.py +51 -51
  21. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/costant.py +15 -15
  22. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/site.py +84 -84
  23. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/title.py +47 -47
  24. StreamingCommunity/{Src/Api → Api}/Site/cb01new/__init__.py +51 -51
  25. StreamingCommunity/{Src/Api → Api}/Site/cb01new/costant.py +15 -15
  26. StreamingCommunity/{Src/Api → Api}/Site/cb01new/film.py +69 -69
  27. StreamingCommunity/{Src/Api → Api}/Site/cb01new/site.py +74 -74
  28. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/__init__.py +57 -57
  29. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/costant.py +16 -16
  30. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/series.py +141 -142
  31. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/site.py +92 -92
  32. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/util/ScrapeSerie.py +84 -82
  33. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/__init__.py +52 -52
  34. StreamingCommunity/{Src/Api/Site/piratebays → Api/Site/guardaserie}/costant.py +15 -15
  35. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/series.py +195 -195
  36. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/site.py +84 -84
  37. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/util/ScrapeSerie.py +110 -110
  38. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/__init__.py +48 -48
  39. StreamingCommunity/{Src/Api/Site/animeunity → Api/Site/mostraguarda}/costant.py +15 -15
  40. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/film.py +94 -94
  41. StreamingCommunity/{Src/Api → Api}/Site/piratebays/__init__.py +50 -50
  42. StreamingCommunity/{Src/Api/Site/guardaserie → Api/Site/piratebays}/costant.py +15 -15
  43. StreamingCommunity/{Src/Api → Api}/Site/piratebays/site.py +88 -88
  44. StreamingCommunity/{Src/Api → Api}/Site/piratebays/title.py +45 -45
  45. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/__init__.py +55 -55
  46. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/costant.py +15 -15
  47. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/film.py +70 -70
  48. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/series.py +205 -203
  49. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/site.py +125 -125
  50. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/util/ScrapeSerie.py +3 -3
  51. StreamingCommunity/{Src/Api → Api}/Template/Class/SearchType.py +101 -101
  52. StreamingCommunity/{Src/Api → Api}/Template/Util/__init__.py +4 -4
  53. StreamingCommunity/{Src/Api → Api}/Template/Util/get_domain.py +137 -137
  54. StreamingCommunity/{Src/Api → Api}/Template/Util/manage_ep.py +153 -153
  55. StreamingCommunity/{Src/Api → Api}/Template/Util/recall_search.py +37 -37
  56. StreamingCommunity/Api/Template/__init__.py +3 -0
  57. StreamingCommunity/{Src/Api → Api}/Template/site.py +87 -87
  58. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/downloader.py +968 -968
  59. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/proxyes.py +110 -110
  60. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/segments.py +538 -540
  61. StreamingCommunity/{Src/Lib → Lib}/Downloader/MP4/downloader.py +156 -156
  62. StreamingCommunity/{Src/Lib → Lib}/Downloader/TOR/downloader.py +222 -222
  63. StreamingCommunity/{Src/Lib → Lib}/Downloader/__init__.py +4 -4
  64. StreamingCommunity/{Src/Lib → Lib}/Driver/driver_1.py +76 -76
  65. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/__init__.py +4 -4
  66. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/capture.py +170 -170
  67. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/command.py +292 -292
  68. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/util.py +241 -241
  69. StreamingCommunity/{Src/Lib → Lib}/M3U8/__init__.py +5 -5
  70. StreamingCommunity/{Src/Lib → Lib}/M3U8/decryptor.py +164 -129
  71. StreamingCommunity/{Src/Lib → Lib}/M3U8/estimator.py +175 -172
  72. StreamingCommunity/{Src/Lib → Lib}/M3U8/parser.py +666 -666
  73. StreamingCommunity/{Src/Lib → Lib}/M3U8/url_fixer.py +51 -51
  74. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  75. StreamingCommunity/{Src/Lib → Lib}/TMBD/obj_tmbd.py +39 -39
  76. StreamingCommunity/{Src/Lib → Lib}/TMBD/tmdb.py +345 -345
  77. StreamingCommunity/{Src/Upload → Upload}/update.py +68 -64
  78. StreamingCommunity/{Src/Upload → Upload}/version.py +5 -5
  79. StreamingCommunity/{Src/Util → Util}/_jsonConfig.py +204 -204
  80. StreamingCommunity/{Src/Util → Util}/call_stack.py +42 -42
  81. StreamingCommunity/{Src/Util → Util}/color.py +20 -20
  82. StreamingCommunity/{Src/Util → Util}/console.py +12 -12
  83. StreamingCommunity/Util/ffmpeg_installer.py +275 -0
  84. StreamingCommunity/{Src/Util → Util}/headers.py +147 -147
  85. StreamingCommunity/{Src/Util → Util}/logger.py +53 -53
  86. StreamingCommunity/{Src/Util → Util}/message.py +46 -46
  87. StreamingCommunity/{Src/Util → Util}/os.py +514 -417
  88. StreamingCommunity/{Src/Util → Util}/table.py +163 -163
  89. StreamingCommunity/run.py +202 -196
  90. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/METADATA +126 -60
  91. StreamingCommunity-1.9.1.dist-info/RECORD +95 -0
  92. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/WHEEL +1 -1
  93. StreamingCommunity/Src/Api/Site/animeunity/anime.py +0 -126
  94. StreamingCommunity/Src/Api/Site/ddlstreamitaly/Player/ScrapeSerie.py +0 -83
  95. StreamingCommunity/Src/Api/Site/guardaserie/Player/ScrapeSerie.py +0 -110
  96. StreamingCommunity/Src/Api/Template/__init__.py +0 -3
  97. StreamingCommunity/Src/Lib/TMBD/__init__.py +0 -2
  98. StreamingCommunity-1.7.6.dist-info/RECORD +0 -97
  99. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/LICENSE +0 -0
  100. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/entry_points.txt +0 -0
  101. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/top_level.txt +0 -0
@@ -1,292 +1,292 @@
1
- # 31.01.24
2
-
3
- import sys
4
- import time
5
- import logging
6
- import subprocess
7
- from typing import List, Dict
8
-
9
-
10
- # Internal utilities
11
- from StreamingCommunity.Src.Util._jsonConfig import config_manager
12
- from StreamingCommunity.Src.Util.os import os_manager, suppress_output
13
- from StreamingCommunity.Src.Util.console import console
14
- from .util import need_to_force_to_ts, check_duration_v_a
15
- from .capture import capture_ffmpeg_real_time
16
- from ..M3U8 import M3U8_Codec
17
-
18
-
19
- # Config
20
- DEBUG_MODE = config_manager.get_bool("DEFAULT", "debug")
21
- DEBUG_FFMPEG = "debug" if DEBUG_MODE else "error"
22
- USE_CODEC = config_manager.get_bool("M3U8_CONVERSION", "use_codec")
23
- USE_VCODEC = config_manager.get_bool("M3U8_CONVERSION", "use_vcodec")
24
- USE_ACODEC = config_manager.get_bool("M3U8_CONVERSION", "use_acodec")
25
- USE_BITRATE = config_manager.get_bool("M3U8_CONVERSION", "use_bitrate")
26
- USE_GPU = config_manager.get_bool("M3U8_CONVERSION", "use_gpu")
27
- FFMPEG_DEFAULT_PRESET = config_manager.get("M3U8_CONVERSION", "default_preset")
28
-
29
-
30
- # Variable
31
- TQDM_USE_LARGE_BAR = config_manager.get_int('M3U8_DOWNLOAD', 'tqdm_use_large_bar')
32
-
33
-
34
- def join_video(video_path: str, out_path: str, codec: M3U8_Codec = None):
35
-
36
- """
37
- Joins single ts video file to mp4
38
-
39
- Parameters:
40
- - video_path (str): The path to the video file.
41
- - out_path (str): The path to save the output file.
42
- - vcodec (str): The video codec to use. Defaults to 'copy'.
43
- - acodec (str): The audio codec to use. Defaults to 'aac'.
44
- - bitrate (str): The bitrate for the audio stream. Defaults to '192k'.
45
- - force_ts (bool): Force video path to be mpegts as input.
46
- """
47
-
48
- if not os_manager.check_file(video_path):
49
- logging.error("Missing input video for ffmpeg conversion.")
50
- sys.exit(0)
51
-
52
- # Start command
53
- ffmpeg_cmd = ['ffmpeg']
54
-
55
- # Enabled the use of gpu
56
- if USE_GPU:
57
- ffmpeg_cmd.extend(['-hwaccel', 'cuda'])
58
-
59
- # Add mpegts to force to detect input file as ts file
60
- if need_to_force_to_ts(video_path):
61
- console.log("[red]Force input file to 'mpegts'.")
62
- ffmpeg_cmd.extend(['-f', 'mpegts'])
63
- vcodec = "libx264"
64
-
65
- # Insert input video path
66
- ffmpeg_cmd.extend(['-i', video_path])
67
-
68
- # Add output Parameters
69
- if USE_CODEC and codec != None:
70
- if USE_VCODEC:
71
- if codec.video_codec_name:
72
- if not USE_GPU:
73
- ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
74
- else:
75
- ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
76
- else:
77
- console.log("[red]Cant find vcodec for 'join_audios'")
78
- else:
79
- if USE_GPU:
80
- ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
81
-
82
-
83
- if USE_ACODEC:
84
- if codec.audio_codec_name:
85
- ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
86
- else:
87
- console.log("[red]Cant find acodec for 'join_audios'")
88
-
89
- if USE_BITRATE:
90
- ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
91
- ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
92
-
93
- else:
94
- ffmpeg_cmd.extend(['-c', 'copy'])
95
-
96
- # Ultrafast preset always or fast for gpu
97
- if not USE_GPU:
98
- ffmpeg_cmd.extend(['-preset', FFMPEG_DEFAULT_PRESET])
99
- else:
100
- ffmpeg_cmd.extend(['-preset', 'fast'])
101
-
102
- # Overwrite
103
- ffmpeg_cmd += [out_path, "-y"]
104
-
105
- # Run join
106
- if DEBUG_MODE:
107
- subprocess.run(ffmpeg_cmd, check=True)
108
- else:
109
-
110
- if TQDM_USE_LARGE_BAR:
111
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
112
- print()
113
-
114
- else:
115
- console.log(f"[purple]FFmpeg [white][[cyan]Join video[white]] ...")
116
- with suppress_output():
117
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
118
- print()
119
-
120
- time.sleep(0.5)
121
- if not os_manager.check_file(out_path):
122
- logging.error("Missing output video for ffmpeg conversion video.")
123
- sys.exit(0)
124
-
125
-
126
- def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: str, codec: M3U8_Codec = None):
127
- """
128
- Joins audio tracks with a video file using FFmpeg.
129
-
130
- Parameters:
131
- - video_path (str): The path to the video file.
132
- - audio_tracks (list[dict[str, str]]): A list of dictionaries containing information about audio tracks.
133
- Each dictionary should contain the 'path' key with the path to the audio file.
134
- - out_path (str): The path to save the output file.
135
- """
136
-
137
- if not os_manager.check_file(video_path):
138
- logging.error("Missing input video for ffmpeg conversion.")
139
- sys.exit(0)
140
-
141
- video_audio_same_duration = check_duration_v_a(video_path, audio_tracks[0].get('path'))
142
-
143
- # Start command
144
- ffmpeg_cmd = ['ffmpeg']
145
-
146
- # Enabled the use of gpu
147
- if USE_GPU:
148
- ffmpeg_cmd.extend(['-hwaccel', 'cuda'])
149
-
150
- # Insert input video path
151
- ffmpeg_cmd.extend(['-i', video_path])
152
-
153
- # Add audio tracks as input
154
- for i, audio_track in enumerate(audio_tracks):
155
- if os_manager.check_file(audio_track.get('path')):
156
- ffmpeg_cmd.extend(['-i', audio_track.get('path')])
157
- else:
158
- logging.error(f"Skip audio join: {audio_track.get('path')} dont exist")
159
-
160
- # Map the video and audio streams
161
- ffmpeg_cmd.append('-map')
162
- ffmpeg_cmd.append('0:v') # Map video stream from the first input (video_path)
163
-
164
- for i in range(1, len(audio_tracks) + 1):
165
- ffmpeg_cmd.append('-map')
166
- ffmpeg_cmd.append(f'{i}:a') # Map audio streams from subsequent inputs
167
-
168
- # Add output Parameters
169
- if USE_CODEC:
170
- if USE_VCODEC:
171
- if codec.video_codec_name:
172
- if not USE_GPU:
173
- ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
174
- else:
175
- ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
176
- else:
177
- console.log("[red]Cant find vcodec for 'join_audios'")
178
- else:
179
- if USE_GPU:
180
- ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
181
-
182
- if USE_ACODEC:
183
- if codec.audio_codec_name:
184
- ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
185
- else:
186
- console.log("[red]Cant find acodec for 'join_audios'")
187
-
188
- if USE_BITRATE:
189
- ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
190
- ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
191
-
192
- else:
193
- ffmpeg_cmd.extend(['-c', 'copy'])
194
-
195
- # Ultrafast preset always or fast for gpu
196
- if not USE_GPU:
197
- ffmpeg_cmd.extend(['-preset', FFMPEG_DEFAULT_PRESET])
198
- else:
199
- ffmpeg_cmd.extend(['-preset', 'fast'])
200
-
201
- # Use shortest input path for video and audios
202
- if not video_audio_same_duration:
203
- logging.info("[red]Use shortest input.")
204
- ffmpeg_cmd.extend(['-shortest', '-strict', 'experimental'])
205
-
206
- # Overwrite
207
- ffmpeg_cmd += [out_path, "-y"]
208
-
209
- # Run join
210
- if DEBUG_MODE:
211
- subprocess.run(ffmpeg_cmd, check=True)
212
- else:
213
-
214
- if TQDM_USE_LARGE_BAR:
215
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
216
- print()
217
-
218
- else:
219
- console.log(f"[purple]FFmpeg [white][[cyan]Join audio[white]] ...")
220
- with suppress_output():
221
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
222
- print()
223
-
224
- time.sleep(0.5)
225
- if not os_manager.check_file(out_path):
226
- logging.error("Missing output video for ffmpeg conversion audio.")
227
- sys.exit(0)
228
-
229
-
230
- def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_path: str):
231
- """
232
- Joins subtitles with a video file using FFmpeg.
233
-
234
- Parameters:
235
- - video (str): The path to the video file.
236
- - subtitles_list (list[dict[str, str]]): A list of dictionaries containing information about subtitles.
237
- Each dictionary should contain the 'path' key with the path to the subtitle file and the 'name' key with the name of the subtitle.
238
- - out_path (str): The path to save the output file.
239
- """
240
-
241
- if not os_manager.check_file(video_path):
242
- logging.error("Missing input video for ffmpeg conversion.")
243
- sys.exit(0)
244
-
245
- # Start command
246
- ffmpeg_cmd = ["ffmpeg", "-i", video_path]
247
-
248
- # Add subtitle input files first
249
- for subtitle in subtitles_list:
250
- if os_manager.check_file(subtitle.get('path')):
251
- ffmpeg_cmd += ["-i", subtitle['path']]
252
- else:
253
- logging.error(f"Skip subtitle join: {subtitle.get('path')} doesn't exist")
254
-
255
- # Add maps for video and audio streams
256
- ffmpeg_cmd += ["-map", "0:v", "-map", "0:a"]
257
-
258
- # Add subtitle maps and metadata
259
- for idx, subtitle in enumerate(subtitles_list):
260
- ffmpeg_cmd += ["-map", f"{idx + 1}:s"]
261
- ffmpeg_cmd += ["-metadata:s:s:{}".format(idx), "title={}".format(subtitle['language'])]
262
-
263
- # Add output Parameters
264
- if USE_CODEC:
265
- ffmpeg_cmd.extend(['-c:v', 'copy', '-c:a', 'copy', '-c:s', 'mov_text'])
266
- else:
267
- ffmpeg_cmd.extend(['-c', 'copy', '-c:s', 'mov_text'])
268
-
269
- # Overwrite
270
- ffmpeg_cmd += [out_path, "-y"]
271
- logging.info(f"FFmpeg command: {ffmpeg_cmd}")
272
-
273
-
274
- # Run join
275
- if DEBUG_MODE:
276
- subprocess.run(ffmpeg_cmd, check=True)
277
- else:
278
-
279
- if TQDM_USE_LARGE_BAR:
280
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
281
- print()
282
-
283
- else:
284
- console.log(f"[purple]FFmpeg [white][[cyan]Join subtitle[white]] ...")
285
- with suppress_output():
286
- capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
287
- print()
288
-
289
- time.sleep(0.5)
290
- if not os_manager.check_file(out_path):
291
- logging.error("Missing output video for ffmpeg conversion subtitle.")
292
- sys.exit(0)
1
+ # 31.01.24
2
+
3
+ import sys
4
+ import time
5
+ import logging
6
+ import subprocess
7
+ from typing import List, Dict
8
+
9
+
10
+ # Internal utilities
11
+ from StreamingCommunity.Util._jsonConfig import config_manager
12
+ from StreamingCommunity.Util.os import os_manager, suppress_output
13
+ from StreamingCommunity.Util.console import console
14
+ from .util import need_to_force_to_ts, check_duration_v_a
15
+ from .capture import capture_ffmpeg_real_time
16
+ from ..M3U8 import M3U8_Codec
17
+
18
+
19
+ # Config
20
+ DEBUG_MODE = config_manager.get_bool("DEFAULT", "debug")
21
+ DEBUG_FFMPEG = "debug" if DEBUG_MODE else "error"
22
+ USE_CODEC = config_manager.get_bool("M3U8_CONVERSION", "use_codec")
23
+ USE_VCODEC = config_manager.get_bool("M3U8_CONVERSION", "use_vcodec")
24
+ USE_ACODEC = config_manager.get_bool("M3U8_CONVERSION", "use_acodec")
25
+ USE_BITRATE = config_manager.get_bool("M3U8_CONVERSION", "use_bitrate")
26
+ USE_GPU = config_manager.get_bool("M3U8_CONVERSION", "use_gpu")
27
+ FFMPEG_DEFAULT_PRESET = config_manager.get("M3U8_CONVERSION", "default_preset")
28
+
29
+
30
+ # Variable
31
+ TQDM_USE_LARGE_BAR = config_manager.get_int('M3U8_DOWNLOAD', 'tqdm_use_large_bar')
32
+
33
+
34
+ def join_video(video_path: str, out_path: str, codec: M3U8_Codec = None):
35
+
36
+ """
37
+ Joins single ts video file to mp4
38
+
39
+ Parameters:
40
+ - video_path (str): The path to the video file.
41
+ - out_path (str): The path to save the output file.
42
+ - vcodec (str): The video codec to use. Defaults to 'copy'.
43
+ - acodec (str): The audio codec to use. Defaults to 'aac'.
44
+ - bitrate (str): The bitrate for the audio stream. Defaults to '192k'.
45
+ - force_ts (bool): Force video path to be mpegts as input.
46
+ """
47
+
48
+ if not os_manager.check_file(video_path):
49
+ logging.error("Missing input video for ffmpeg conversion.")
50
+ sys.exit(0)
51
+
52
+ # Start command
53
+ ffmpeg_cmd = ['ffmpeg']
54
+
55
+ # Enabled the use of gpu
56
+ if USE_GPU:
57
+ ffmpeg_cmd.extend(['-hwaccel', 'cuda'])
58
+
59
+ # Add mpegts to force to detect input file as ts file
60
+ if need_to_force_to_ts(video_path):
61
+ console.log("[red]Force input file to 'mpegts'.")
62
+ ffmpeg_cmd.extend(['-f', 'mpegts'])
63
+ vcodec = "libx264"
64
+
65
+ # Insert input video path
66
+ ffmpeg_cmd.extend(['-i', video_path])
67
+
68
+ # Add output Parameters
69
+ if USE_CODEC and codec != None:
70
+ if USE_VCODEC:
71
+ if codec.video_codec_name:
72
+ if not USE_GPU:
73
+ ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
74
+ else:
75
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
76
+ else:
77
+ console.log("[red]Cant find vcodec for 'join_audios'")
78
+ else:
79
+ if USE_GPU:
80
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
81
+
82
+
83
+ if USE_ACODEC:
84
+ if codec.audio_codec_name:
85
+ ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
86
+ else:
87
+ console.log("[red]Cant find acodec for 'join_audios'")
88
+
89
+ if USE_BITRATE:
90
+ ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
91
+ ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
92
+
93
+ else:
94
+ ffmpeg_cmd.extend(['-c', 'copy'])
95
+
96
+ # Ultrafast preset always or fast for gpu
97
+ if not USE_GPU:
98
+ ffmpeg_cmd.extend(['-preset', FFMPEG_DEFAULT_PRESET])
99
+ else:
100
+ ffmpeg_cmd.extend(['-preset', 'fast'])
101
+
102
+ # Overwrite
103
+ ffmpeg_cmd += [out_path, "-y"]
104
+
105
+ # Run join
106
+ if DEBUG_MODE:
107
+ subprocess.run(ffmpeg_cmd, check=True)
108
+ else:
109
+
110
+ if TQDM_USE_LARGE_BAR:
111
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
112
+ print()
113
+
114
+ else:
115
+ console.log(f"[purple]FFmpeg [white][[cyan]Join video[white]] ...")
116
+ with suppress_output():
117
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
118
+ print()
119
+
120
+ time.sleep(0.5)
121
+ if not os_manager.check_file(out_path):
122
+ logging.error("Missing output video for ffmpeg conversion video.")
123
+ sys.exit(0)
124
+
125
+
126
+ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: str, codec: M3U8_Codec = None):
127
+ """
128
+ Joins audio tracks with a video file using FFmpeg.
129
+
130
+ Parameters:
131
+ - video_path (str): The path to the video file.
132
+ - audio_tracks (list[dict[str, str]]): A list of dictionaries containing information about audio tracks.
133
+ Each dictionary should contain the 'path' key with the path to the audio file.
134
+ - out_path (str): The path to save the output file.
135
+ """
136
+
137
+ if not os_manager.check_file(video_path):
138
+ logging.error("Missing input video for ffmpeg conversion.")
139
+ sys.exit(0)
140
+
141
+ video_audio_same_duration = check_duration_v_a(video_path, audio_tracks[0].get('path'))
142
+
143
+ # Start command
144
+ ffmpeg_cmd = ['ffmpeg']
145
+
146
+ # Enabled the use of gpu
147
+ if USE_GPU:
148
+ ffmpeg_cmd.extend(['-hwaccel', 'cuda'])
149
+
150
+ # Insert input video path
151
+ ffmpeg_cmd.extend(['-i', video_path])
152
+
153
+ # Add audio tracks as input
154
+ for i, audio_track in enumerate(audio_tracks):
155
+ if os_manager.check_file(audio_track.get('path')):
156
+ ffmpeg_cmd.extend(['-i', audio_track.get('path')])
157
+ else:
158
+ logging.error(f"Skip audio join: {audio_track.get('path')} dont exist")
159
+
160
+ # Map the video and audio streams
161
+ ffmpeg_cmd.append('-map')
162
+ ffmpeg_cmd.append('0:v') # Map video stream from the first input (video_path)
163
+
164
+ for i in range(1, len(audio_tracks) + 1):
165
+ ffmpeg_cmd.append('-map')
166
+ ffmpeg_cmd.append(f'{i}:a') # Map audio streams from subsequent inputs
167
+
168
+ # Add output Parameters
169
+ if USE_CODEC:
170
+ if USE_VCODEC:
171
+ if codec.video_codec_name:
172
+ if not USE_GPU:
173
+ ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
174
+ else:
175
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
176
+ else:
177
+ console.log("[red]Cant find vcodec for 'join_audios'")
178
+ else:
179
+ if USE_GPU:
180
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
181
+
182
+ if USE_ACODEC:
183
+ if codec.audio_codec_name:
184
+ ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
185
+ else:
186
+ console.log("[red]Cant find acodec for 'join_audios'")
187
+
188
+ if USE_BITRATE:
189
+ ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
190
+ ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
191
+
192
+ else:
193
+ ffmpeg_cmd.extend(['-c', 'copy'])
194
+
195
+ # Ultrafast preset always or fast for gpu
196
+ if not USE_GPU:
197
+ ffmpeg_cmd.extend(['-preset', FFMPEG_DEFAULT_PRESET])
198
+ else:
199
+ ffmpeg_cmd.extend(['-preset', 'fast'])
200
+
201
+ # Use shortest input path for video and audios
202
+ if not video_audio_same_duration:
203
+ logging.info("[red]Use shortest input.")
204
+ ffmpeg_cmd.extend(['-shortest', '-strict', 'experimental'])
205
+
206
+ # Overwrite
207
+ ffmpeg_cmd += [out_path, "-y"]
208
+
209
+ # Run join
210
+ if DEBUG_MODE:
211
+ subprocess.run(ffmpeg_cmd, check=True)
212
+ else:
213
+
214
+ if TQDM_USE_LARGE_BAR:
215
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
216
+ print()
217
+
218
+ else:
219
+ console.log(f"[purple]FFmpeg [white][[cyan]Join audio[white]] ...")
220
+ with suppress_output():
221
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
222
+ print()
223
+
224
+ time.sleep(0.5)
225
+ if not os_manager.check_file(out_path):
226
+ logging.error("Missing output video for ffmpeg conversion audio.")
227
+ sys.exit(0)
228
+
229
+
230
+ def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_path: str):
231
+ """
232
+ Joins subtitles with a video file using FFmpeg.
233
+
234
+ Parameters:
235
+ - video (str): The path to the video file.
236
+ - subtitles_list (list[dict[str, str]]): A list of dictionaries containing information about subtitles.
237
+ Each dictionary should contain the 'path' key with the path to the subtitle file and the 'name' key with the name of the subtitle.
238
+ - out_path (str): The path to save the output file.
239
+ """
240
+
241
+ if not os_manager.check_file(video_path):
242
+ logging.error("Missing input video for ffmpeg conversion.")
243
+ sys.exit(0)
244
+
245
+ # Start command
246
+ ffmpeg_cmd = ["ffmpeg", "-i", video_path]
247
+
248
+ # Add subtitle input files first
249
+ for subtitle in subtitles_list:
250
+ if os_manager.check_file(subtitle.get('path')):
251
+ ffmpeg_cmd += ["-i", subtitle['path']]
252
+ else:
253
+ logging.error(f"Skip subtitle join: {subtitle.get('path')} doesn't exist")
254
+
255
+ # Add maps for video and audio streams
256
+ ffmpeg_cmd += ["-map", "0:v", "-map", "0:a"]
257
+
258
+ # Add subtitle maps and metadata
259
+ for idx, subtitle in enumerate(subtitles_list):
260
+ ffmpeg_cmd += ["-map", f"{idx + 1}:s"]
261
+ ffmpeg_cmd += ["-metadata:s:s:{}".format(idx), "title={}".format(subtitle['language'])]
262
+
263
+ # Add output Parameters
264
+ if USE_CODEC:
265
+ ffmpeg_cmd.extend(['-c:v', 'copy', '-c:a', 'copy', '-c:s', 'mov_text'])
266
+ else:
267
+ ffmpeg_cmd.extend(['-c', 'copy', '-c:s', 'mov_text'])
268
+
269
+ # Overwrite
270
+ ffmpeg_cmd += [out_path, "-y"]
271
+ logging.info(f"FFmpeg command: {ffmpeg_cmd}")
272
+
273
+
274
+ # Run join
275
+ if DEBUG_MODE:
276
+ subprocess.run(ffmpeg_cmd, check=True)
277
+ else:
278
+
279
+ if TQDM_USE_LARGE_BAR:
280
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
281
+ print()
282
+
283
+ else:
284
+ console.log(f"[purple]FFmpeg [white][[cyan]Join subtitle[white]] ...")
285
+ with suppress_output():
286
+ capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
287
+ print()
288
+
289
+ time.sleep(0.5)
290
+ if not os_manager.check_file(out_path):
291
+ logging.error("Missing output video for ffmpeg conversion subtitle.")
292
+ sys.exit(0)