udemy-userAPI 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
udemy_userAPI/sections.py CHANGED
@@ -12,7 +12,7 @@ def get_courses_plan(tipe: str) -> list:
12
12
  from .authenticate import UdemyAuth
13
13
  auth = UdemyAuth()
14
14
  if not auth.verif_login():
15
- raise LoginException("Seção expirada!")
15
+ raise LoginException("Sessão expirada!")
16
16
  courses_data = []
17
17
  if tipe == 'default':
18
18
  response = requests.get(f"https://www.udemy.com/api-2.0/users/me/subscribed-courses/?page_size=1000"
@@ -69,7 +69,7 @@ def get_details_courses(course_id):
69
69
  from .authenticate import UdemyAuth
70
70
  auth = UdemyAuth()
71
71
  if not auth.verif_login():
72
- raise LoginException("Seção expirada!")
72
+ raise LoginException("Sessão expirada!")
73
73
  response = requests.get(
74
74
  f"https://www.udemy.com/api-2.0/courses/{course_id}/subscriber-curriculum-items/?"
75
75
  f"caching_intent=True&fields%5Basset%5D=title%2Cfilename%2Casset_type%2Cstatus%2Ctime_estimation%2"
@@ -105,7 +105,7 @@ def get_course_infor(course_id):
105
105
  from .authenticate import UdemyAuth
106
106
  auth = UdemyAuth()
107
107
  if not auth.verif_login():
108
- raise LoginException("Seção expirada!")
108
+ raise LoginException("Sessão expirada!")
109
109
  end_point = (
110
110
  f'https://www.udemy.com/api-2.0/courses/{course_id}/?fields[course]=title,context_info,primary_category,'
111
111
  'primary_subcategory,avg_rating_recent,visible_instructors,locale,estimated_content_length,'
udemy_userAPI/udemy.py CHANGED
@@ -20,7 +20,7 @@ class Udemy:
20
20
  """
21
21
  self.__headers = HEADERS_USER
22
22
  if not verif_login:
23
- raise LoginException("Seção expirada!")
23
+ raise LoginException("Sessão expirada!")
24
24
 
25
25
  @staticmethod
26
26
  def my_subscribed_courses_by_plan() -> list[dict]:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: udemy_userAPI
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: Obtenha detalhes de cursos que o usuário esteja inscrito da plataforma Udemy,usando o EndPoint de usuário o mesmo que o navegador utiliza para acessar e redenrizar os cursos.
5
5
  Author: PauloCesar-dev404
6
6
  Author-email: paulocesar0073dev404@gmail.com
@@ -15,11 +15,21 @@ License-File: LICENSE
15
15
  Requires-Dist: requests
16
16
  Requires-Dist: cloudscraper
17
17
  Requires-Dist: pywidevine
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: keywords
23
+ Dynamic: license
24
+ Dynamic: platform
25
+ Dynamic: project-url
26
+ Dynamic: requires-dist
27
+ Dynamic: summary
18
28
 
19
29
  # udemy-userAPI
20
30
 
21
31
 
22
- ![Versão](https://img.shields.io/badge/version-0.3.4-orange)
32
+ ![Versão](https://img.shields.io/badge/version-0.3.6-orange)
23
33
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
24
34
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://paulocesar-dev404.github.io/me-apoiando-online/)
25
35
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
@@ -0,0 +1,17 @@
1
+ udemy_userAPI/__init__.py,sha256=BPle89xE_CMTKKe_Lw6jioYLgpH-q_Lpho2S-n1PIUA,206
2
+ udemy_userAPI/__version__.py,sha256=EcE9Js6ZcOzm6ll-14ArSvYXxNzDsRtEfpRK27AHgtA,405
3
+ udemy_userAPI/api.py,sha256=jWWwJBYS9dJDjlozUj4Yi4uc8OCAy5PILqUiRWZMiq8,28153
4
+ udemy_userAPI/authenticate.py,sha256=IJRrCjmhe_x40CrQ2KrOMNP8VvotZf0QMWsrbcLl_rw,14225
5
+ udemy_userAPI/bultins.py,sha256=I2jKaOL6ExSQg7zMaGvaJGLym4L7GXo9WWvNeDbrm2I,18629
6
+ udemy_userAPI/exeptions.py,sha256=kfnPdZpqYY8nd0gnl6_Vh-MIz-XupmmbRPIuFnyXupk,692
7
+ udemy_userAPI/sections.py,sha256=oP3jvbsWocemqhzzOAOoeL7ICF1f4gNvjL4FJBt47pE,5474
8
+ udemy_userAPI/udemy.py,sha256=SpK0LI4hjO45nZDz5waw-Py-d0uulBb28TVjltyWBxM,2920
9
+ udemy_userAPI/.cache/.udemy_userAPI,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ udemy_userAPI/mpd_analyzer/__init__.py,sha256=i3JVWyvcFLaj5kPmx8c1PgjsLht7OUIQQClD4yqYbo8,102
11
+ udemy_userAPI/mpd_analyzer/bin.wvd,sha256=1rAJdCc120hQlX9qe5KUS628eY2ZHYxQSmyhGNefSzo,2956
12
+ udemy_userAPI/mpd_analyzer/mpd_parser.py,sha256=PgUkHc5x8FTuXFCuYkWPZr9TaO_nsKalb02EFYl_zeA,8926
13
+ udemy_userAPI-0.3.6.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
14
+ udemy_userAPI-0.3.6.dist-info/METADATA,sha256=LUarfagN6sbQ5BgJDvHSJdFAEFhi18vCSDF5DKOMw70,1655
15
+ udemy_userAPI-0.3.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
16
+ udemy_userAPI-0.3.6.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
17
+ udemy_userAPI-0.3.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1 +0,0 @@
1
- from .animation import AnimationConsole
@@ -1,64 +0,0 @@
1
- import sys
2
- import time
3
- import threading
4
- from colorama import init, Fore, Style
5
-
6
- # Inicializa o suporte a cores no Windows
7
- init(autoreset=True)
8
-
9
-
10
- class AnimationConsole:
11
- def __init__(self, text="Loading", color=Fore.GREEN, color_frame=Fore.BLUE):
12
- """
13
- Cria uma animação de loading com uma mensagem colorida no console.
14
- :param text: Texto inicial da mensagem de loading.
15
- :param color: Cor do texto, usando Fore do colorama.
16
- """
17
- self._color_frame = color_frame
18
- self._text = text
19
- self._color = color
20
- self._running = False
21
- self._animation_thread = None
22
- self._frames = ["-", "\\", "|", "/"]
23
- self._index = 0
24
-
25
- def start(self):
26
- """
27
- Inicia a animação no console.
28
- """
29
- if self._running:
30
- return # Previne múltiplas execuções
31
- self._running = True
32
- self._animation_thread = threading.Thread(target=self._animate, daemon=True)
33
- self._animation_thread.start()
34
-
35
- def stop(self):
36
- """
37
- Para a animação no console.
38
- """
39
- self._running = False
40
- if self._animation_thread:
41
- self._animation_thread.join()
42
- sys.stdout.write("\r" + " " * (len(self._text) + 20) + "\r") # Limpa a linha
43
-
44
- def update_message(self, new_text, new_color=None):
45
- """
46
- Atualiza a mensagem exibida junto à animação.
47
- :param new_text: Novo texto a ser exibido.
48
- :param new_color: Nova cor para o texto (opcional).
49
- """
50
- self._text = new_text
51
- if new_color:
52
- self._color = new_color
53
-
54
- def _animate(self):
55
- """
56
- Animação interna do console.
57
- """
58
- while self._running:
59
- frame = self._frames[self._index]
60
- self._index = (self._index + 1) % len(self._frames)
61
- sys.stdout.write(
62
- f"\r{self._color}{self._text}{Style.RESET_ALL} {self._color_frame}{frame}{Style.RESET_ALL}")
63
- sys.stdout.flush()
64
- time.sleep(0.1)
@@ -1,118 +0,0 @@
1
- import sys
2
- import os
3
- import requests
4
- import zipfile
5
- import shutil
6
- import stat
7
- from .exeptions import *
8
- from .__utils import URL_PLATAFOMR, system
9
-
10
- lib_name = os.path.dirname(__file__)
11
- URL_BASE_REPO = "https://raw.githubusercontent.com/PauloCesar-dev404/binarios/main/"
12
-
13
-
14
- class Configurate:
15
- """Configura variáveis de ambiente no ambiente virtual ou globalmente."""
16
-
17
- def __init__(self):
18
- self.VERSION = self.__read_version
19
- self.FFMPEG_URL = os.getenv('FFMPEG_URL')
20
- self.FFMPEG_BINARY = os.getenv('FFMPEG_BINARY')
21
- PATH = os.path.join(lib_name, 'ffmpeg-bin')
22
- os.makedirs(PATH, exist_ok=True)
23
- dirpath = PATH
24
- self.INSTALL_DIR = os.getenv('INSTALL_DIR', dirpath)
25
- self.configure()
26
-
27
- def configure(self):
28
- """Configura as variáveis de ambiente com base no sistema operacional."""
29
- if not self.FFMPEG_URL or not self.FFMPEG_BINARY:
30
- platform_name = system
31
- if platform_name == 'Windows':
32
- self.FFMPEG_URL = URL_PLATAFOMR
33
- self.FFMPEG_BINARY = 'ffmpeg.exe'
34
- elif platform_name == 'Linux':
35
- self.FFMPEG_URL = URL_PLATAFOMR
36
- self.FFMPEG_BINARY = 'ffmpeg'
37
- else:
38
- raise DeprecationWarning(f"Arquitetura '{platform_name}' ainda não suportada...\n\n"
39
- f"Versão atual da lib: {self.VERSION}")
40
- os.environ['FFMPEG_URL'] = self.FFMPEG_URL
41
- os.environ['FFMPEG_BINARY'] = self.FFMPEG_BINARY
42
-
43
- if not os.getenv('INSTALL_DIR'):
44
- os.environ['INSTALL_DIR'] = self.INSTALL_DIR
45
-
46
- @property
47
- def __read_version(self):
48
- """Lê a versão do arquivo __version__.py."""
49
- version_file = os.path.join(os.path.dirname(os.path.abspath(__file__)).split('.')[0], '__version__.py')
50
- if os.path.isfile(version_file):
51
- with open(version_file, 'r') as file:
52
- version_line = file.readline().strip()
53
- if version_line.startswith('__version__'):
54
- return version_line.split('=')[1].strip().strip("'")
55
- return 'Unknown Version'
56
-
57
- def __download_file(self, url: str, local_filename: str):
58
- """Baixa um arquivo do URL para o caminho local especificado."""
59
- try:
60
- response = requests.get(url, stream=True)
61
- response.raise_for_status()
62
- total_length = int(response.headers.get('content-length', 0))
63
-
64
- with open(local_filename, 'wb') as f:
65
- start_time = time.time()
66
- downloaded = 0
67
-
68
- for data in response.iter_content(chunk_size=4096):
69
- downloaded += len(data)
70
- f.write(data)
71
-
72
- elapsed_time = time.time() - start_time
73
- elapsed_time = max(elapsed_time, 0.001)
74
- speed_kbps = (downloaded / 1024) / elapsed_time
75
- percent_done = (downloaded / total_length) * 100
76
-
77
-
78
- except requests.RequestException as e:
79
- raise Exception(f"Erro durante o download: {e}")
80
-
81
- def __extract_zip(self, zip_path: str, extract_to: str):
82
- """Descompacta o arquivo ZIP no diretório especificado."""
83
- try:
84
- with zipfile.ZipFile(zip_path, 'r') as zip_ref:
85
- zip_ref.extractall(extract_to)
86
- except zipfile.BadZipFile as e:
87
- sys.stderr.write(f"Erro ao descompactar o arquivo: {e}\n")
88
- raise
89
- finally:
90
- os.remove(zip_path)
91
-
92
- def remove_file(self, file_path: str):
93
- """Remove o arquivo ou diretório especificado."""
94
- if os.path.exists(file_path):
95
- try:
96
- shutil.rmtree(file_path, onerror=self.handle_remove_readonly)
97
- except Exception as e:
98
- print(f"Erro ao remover {file_path}: {e}")
99
- raise
100
-
101
- def install_bins(self):
102
- """Instala o ffmpeg baixando e descompactando o binário apropriado."""
103
- zip_path = os.path.join(self.INSTALL_DIR, "ffmpeg.zip")
104
- os.makedirs(self.INSTALL_DIR, exist_ok=True)
105
- self.__download_file(self.FFMPEG_URL, zip_path)
106
- self.__extract_zip(zip_path, self.INSTALL_DIR)
107
- self.remove_file(zip_path)
108
- os.environ["PATH"] += os.pathsep + self.INSTALL_DIR
109
- return
110
-
111
- def handle_remove_readonly(self, func, path, exc_info):
112
- """Callback para lidar com arquivos somente leitura."""
113
- os.chmod(path, stat.S_IWRITE)
114
- func(path)
115
-
116
-
117
- if __name__ == "__main__":
118
- FFmpegExceptions("erro de runtime...")
@@ -1,8 +0,0 @@
1
- # ffmpeg-and-python/__init__.py
2
-
3
- from .ffmpeg import FFmpeg
4
- from .exeptions import FFmpegExceptions
5
-
6
- __all__ = ['FFmpeg', 'FFmpegExceptions']
7
- if __name__ == '__main__':
8
- raise RuntimeError("no escope!")
@@ -1,78 +0,0 @@
1
- import platform
2
- import os
3
-
4
- URL_PLATAFOMR = ''
5
-
6
-
7
- def get_processor_info():
8
- system = platform.system()
9
- architecture = platform.architecture()[0]
10
- processor = ''
11
- if system == "Windows":
12
- processor = platform.processor()
13
- elif system in ["Linux", "Darwin"]: # Darwin é o nome do sistema para macOS
14
- try:
15
- if system == "Linux":
16
- # Obtém informações detalhadas do processador no Linux
17
- with open("/proc/cpuinfo") as f:
18
- cpuinfo = f.read()
19
- if "model name" in cpuinfo:
20
- processor = cpuinfo.split("model name")[1].split(":")[1].split("\n")[0].strip()
21
- else:
22
- processor = "Unknown"
23
- elif system == "Darwin":
24
- # Obtém informações detalhadas do processador no macOS
25
- processor = os.popen("sysctl -n machdep.cpu.brand_string").read().strip()
26
- except FileNotFoundError:
27
- processor = "Unknown"
28
- d = (f"System: {system} "
29
- f"Architecture: {architecture} "
30
- f"Processor: {processor} ")
31
- return d
32
-
33
-
34
- # Processa a informação do processador e limpa a string
35
- data = (get_processor_info().replace('Architecture:', '').replace('System:', '').
36
- replace('Processor:', '').strip().split())
37
-
38
- # Remove entradas vazias e limpa espaços em branco
39
- cleaned_data = [item.strip() for item in data if item.strip()]
40
-
41
- # Garantindo que há pelo menos três elementos
42
- if len(cleaned_data) >= 2:
43
- system = cleaned_data[0]
44
- architecture = cleaned_data[1]
45
- processor = ' '.join(cleaned_data[2:]) # Junta o restante como o processador
46
-
47
- URL_BASE_REPO = "https://raw.githubusercontent.com/PauloCesar-dev404/binarios/main/"
48
- # Mapeamento para Linux
49
- linux_mapping = {
50
- "x86_64": "amd64",
51
- "i686": "i686",
52
- "arm64": "arm64",
53
- "armhf": "armhf",
54
- "armel": "armel"
55
- }
56
- # Formata a URL com base no sistema e arquitetura
57
- if system == "Linux" and ('intel' in processor.lower() or 'amd' in processor.lower()):
58
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('x86_64')}.zip"
59
- elif system == "Linux" and 'i686' in architecture.lower():
60
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('i686')}.zip"
61
- elif system == "Linux" and 'arm64' in architecture.lower():
62
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('arm64')}.zip"
63
- elif system == "Linux" and 'armhf' in architecture.lower():
64
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('armhf')}.zip"
65
- elif system == "Linux" and 'armel' in architecture.lower():
66
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('armel')}.zip"
67
- elif system == "Windows" and architecture == '64bit':
68
- url = f"{URL_BASE_REPO}windows/win-ffmpeg-7.0.2-full-amd64-intel64.zip"
69
- else:
70
- url = f"Unsupported system or architecture"
71
-
72
- URL_PLATAFOMR = url
73
-
74
- else:
75
- raise DeprecationWarning("Não foi possível obter seu sistema ....consulte o desenvolvedor!")
76
-
77
- if __name__ == '__main__':
78
- raise RuntimeError("este é uma função interna!")
@@ -1,6 +0,0 @@
1
- __version__ = '0.3.5'
2
- __lib_name__ = 'ffmpeg_for_python'
3
- __autor__ = 'PauloCesar-dev404'
4
- __repo__ = 'https://github.com/PauloCesar-dev404/ffmpeg-for-python'
5
- __lib__ = f'https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/{__lib_name__}-{__version__}-py3-none-any.whl'
6
- __source__ = f'https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/{__lib_name__}-{__version__}.tar.gz'
@@ -1,91 +0,0 @@
1
- import time
2
-
3
- INPUT_ERROR = [
4
- 'Error opening input: No such file or directory',
5
- 'Error opening input: Permission denied',
6
- 'Error opening input: Invalid argument',
7
- 'Error opening input: Protocol not found',
8
- 'Error opening input: Unsupported protocol',
9
- 'Error opening input: File format not recognized',
10
- 'Error opening input: Could not open file',
11
- 'Error opening input: Invalid data found when processing input',
12
- 'Error opening input: Input stream is empty',
13
- 'Error opening input: Cannot open file for reading',
14
- 'Error opening input: File is too short',
15
- 'Error opening input: End of file while parsing input',
16
- 'Error opening input: Codec not found',
17
- 'Error opening input: No decoder for codec',
18
- 'Error opening input: Stream not found',
19
- 'Error opening input: Stream codec not found',
20
- 'Error opening input: Stream index out of range',
21
- 'Error opening input: Invalid timestamp',
22
- 'Error opening input: Corrupt file',
23
- 'Error opening input: Unsupported codec',
24
- 'Error opening input: Failed to initialize filter',
25
- 'Error opening input: Error while opening codec',
26
- 'Error opening input: Device not found',
27
- 'Error opening input: Device or resource busy',
28
- 'Error opening input: Invalid option',
29
- 'Error opening input: Unable to seek',
30
- 'Error opening input: Input format not found'
31
- ]
32
- OUTPUT_ERROR = [
33
- 'Error opening output file: No such file or directory',
34
- 'Error opening output file: Permission denied',
35
- 'Error opening output file: Invalid argument',
36
- 'Error opening output file: Unsupported protocol',
37
- 'Error opening output file: Protocol not found',
38
- 'Error opening output file: File format not recognized',
39
- 'Error opening output file: Could not open file for writing',
40
- 'Error opening output file: Disk full or quota exceeded',
41
- 'Error opening output file: Cannot create file',
42
- 'Error opening output file: Invalid data found when processing output',
43
- 'Error opening output file: Output stream not found',
44
- 'Error opening output file: Cannot write to file',
45
- 'Error opening output file: File already exists',
46
- 'Error opening output file: Unsupported codec',
47
- 'Error opening output file: Codec not found',
48
- 'Error opening output file: Cannot open codec for writing',
49
- 'Error opening output file: Failed to initialize filter',
50
- 'Error opening output file: Invalid option',
51
- 'Error opening output file: Invalid timestamp',
52
- 'Error opening output file: Corrupt file',
53
- 'Error opening output file: Device or resource busy',
54
- 'Error opening output file: Cannot seek',
55
- 'Error opening output file: Stream index out of range',
56
- 'Error opening output file: Stream codec not found'
57
- ]
58
- ERROS = []
59
- for er in INPUT_ERROR:
60
- ERROS.append(er)
61
- for er in OUTPUT_ERROR:
62
- ERROS.append(er)
63
-
64
-
65
- class FFmpegExceptions(Exception):
66
- def __init__(self, message: str):
67
- super().__init__(message)
68
-
69
- def __str__(self):
70
- """
71
- Retorna a representação em string da exceção.
72
-
73
- Returns:
74
- str: Mensagem de erro formatada com detalhes adicionais, se presentes.
75
- """
76
-
77
- return super().__str__()
78
-
79
-
80
- def wraper_erros(line: str):
81
- """Verifica se a linha de saida do ffmpeg está no dict de erros e retorna sua categoria"""
82
-
83
- if "Error" in line:
84
- erro = line.split('Error')[1]
85
- return erro.strip()
86
- elif 'already exists. Overwrite? [y/N]' in line:
87
- erro = line.split('File')[1]
88
- return erro.strip()
89
-
90
-
91
-
@@ -1,203 +0,0 @@
1
- import os
2
- import platform
3
- import subprocess
4
- import time
5
- from typing import List
6
- from .__config__ import Configurate
7
- from .exeptions import wraper_erros, FFmpegExceptions
8
-
9
- parser = Configurate()
10
- parser.configure()
11
- ffmpeg_binarie = os.path.join(parser.INSTALL_DIR, parser.FFMPEG_BINARY)
12
-
13
-
14
- def ffmpeg(cls):
15
- """Decorador que instancia automaticamente a classe FFmpeg."""
16
-
17
- def wrapper(*args, **kwargs):
18
- # Cria e retorna uma instância da classe FFmpeg
19
- instance = cls(*args, **kwargs)
20
- return instance
21
-
22
- return wrapper
23
-
24
-
25
- @ffmpeg
26
- class FFmpeg:
27
- """Wrapper para o binário FFmpeg, permitindo o uso de comandos FFmpeg via Python."""
28
-
29
- def __init__(self):
30
- # Verifica se o binário do FFmpeg existe
31
- if not self.__verify_path(bin_path=ffmpeg_binarie, path_type='file'):
32
- parser.install_bins()
33
- self.__ffmpeg_path = str(ffmpeg_binarie)
34
- self.__command = [self.__ffmpeg_path]
35
- self.__overwrite_output = False
36
-
37
- def args(self, arguments: List[str]) -> 'FFmpeg':
38
- """Adiciona múltiplos argumentos personalizados ao comando FFmpeg."""
39
- if not all(isinstance(arg, str) for arg in arguments):
40
- raise TypeError("All arguments should be provided as strings.")
41
- self.__command.extend(arguments)
42
- return self
43
-
44
- def run(self, capture_output: bool = False):
45
- """Executa o comando FFmpeg construído.
46
-
47
- Args:
48
- capture_output (bool): Se verdadeiro, captura a saída e printa no console.
49
- Se False, a saída é retornada assincronamente em tempo real.
50
-
51
- Yields:
52
- str: Cada linha da saída filtrada do FFmpeg quando capture_output é False.
53
- """
54
-
55
- configs = self.__oculte_comands_your_system.get('startupinfo')
56
-
57
- # Executa o comando utilizando subprocess
58
- with subprocess.Popen(
59
- self.__command,
60
- startupinfo=configs,
61
- stdout=subprocess.PIPE,
62
- stderr=subprocess.PIPE,
63
- stdin=subprocess.PIPE,
64
- text=True,
65
- bufsize=1, # Linha por linha
66
- universal_newlines=True # Garante que novas linhas sejam interpretadas corretamente
67
- ) as process:
68
- try:
69
- # Lê a saída de erro padrão (stderr) em tempo real
70
- for linha in process.stderr:
71
- time.sleep(0.01) # Simulação de latência, opcional
72
-
73
- # Filtra a linha de erro padrão
74
- linha_filtrada = wraper_erros(linha)
75
-
76
- if linha_filtrada:
77
- # Se houver um erro detectado, o processo é encerrado
78
- process.terminate()
79
- raise FFmpegExceptions(message=f'Erro na execução do ffmpeg: "{linha_filtrada}"')
80
- else:
81
- if capture_output:
82
- # Se `capture_output` estiver ativado, imprime a saída
83
- print(linha.strip())
84
- else:
85
- # Retorna a linha assincronamente quando capture_output é False
86
- yield linha.strip()
87
-
88
- # Aguarda a conclusão do processo
89
- process.wait()
90
-
91
- except Exception as e:
92
- process.terminate()
93
- raise FFmpegExceptions(message=f'Erro no processo FFmpeg: {str(e)}')
94
-
95
- def input(self, file_path: str) -> 'FFmpeg':
96
- """Define o arquivo de entrada para o FFmpeg."""
97
- cmd = ['-i', file_path]
98
- self.args(cmd)
99
- return self
100
-
101
- def output(self, output_path: str) -> 'FFmpeg':
102
- """Define o arquivo de saída para o FFmpeg e verifica se a sobrescrita está permitida."""
103
- if os.path.exists(output_path):
104
- if not self.__overwrite_output:
105
- raise FFmpegExceptions(f"O arquivo de saída '{output_path}' já existe! Use 'overwrite_output' para "
106
- f"sobrescrevê-lo.")
107
-
108
- # Adiciona o arquivo de saída ao comando
109
- cmd = [output_path]
110
- self.args(cmd)
111
- return self
112
-
113
- @property
114
- def overwrite_output(self):
115
- """
116
- Adiciona o parâmetro '-y' ao comando FFmpeg, o que permite sobrescrever o arquivo de saída
117
- caso ele já exista.
118
-
119
- Importante: Esta propriedade deve ser definida antes dos parâmetros de entrada e saída
120
- para garantir que o comando FFmpeg seja construído corretamente. Caso contrário, o comando
121
- pode não ser executado como esperado.
122
-
123
- Returns:
124
- FFmpeg: Retorna a instância atual para encadeamento de métodos.
125
- """
126
- self.__overwrite_output = True
127
- cmd = ['-y']
128
- self.args(cmd)
129
- return self
130
-
131
- @property
132
- def hide_banner(self) -> 'FFmpeg':
133
- """oculta o baner do ffmpeg"""
134
- self.__command.extend(['-hide_banner'])
135
- return self
136
-
137
- @property
138
- def copy(self) -> 'FFmpeg':
139
- """Adiciona o parâmetro '-c copy"""
140
- self.__command.extend(['-c', 'copy'])
141
- return self
142
-
143
- @property
144
- def copy_codecs(self):
145
- """para remuxar"""
146
- self.__command.extend(['-c:a', 'copy', '-c:v', 'copy'])
147
- return self
148
-
149
- def reset_ffmpeg(self) -> 'FFmpeg':
150
- """Reseta o comando para reutilização do objeto,isso é necessário em caso de uso em loops,
151
- a cada execução execute o reset para ter certeza que estar limpo o cache de comandos"""
152
- self.__command = [self.__ffmpeg_path]
153
- return self
154
-
155
- @staticmethod
156
- def __verify_path(bin_path, path_type: str) -> bool:
157
- """
158
- Verifica se um caminho de arquivo ou diretório existe.
159
-
160
- Args:
161
- bin_path : O caminho a ser verificado.
162
- path_type (str): O tipo de caminho ('file' para arquivo, 'dir' para diretório).
163
-
164
- Returns:
165
- bool: True se o caminho existir e for do tipo especificado, False caso contrário.
166
- """
167
- if path_type == 'file':
168
- return os.path.isfile(bin_path)
169
- elif path_type == 'dir':
170
- return os.path.isdir(bin_path)
171
- else:
172
- raise ValueError("Invalid path_type. Use 'file' or 'dir'.")
173
-
174
- @property
175
- def __oculte_comands_your_system(self) -> dict:
176
- """Identifica o sistema do usuário e cria um dicionário de parâmetros para ocultar saídas de janelas e do
177
- terminal."""
178
- system_user = platform.system()
179
- startupinfo_options = {}
180
-
181
- if system_user == "Windows":
182
- # Configuração específica para ocultar o terminal no Windows
183
- startupinfo = subprocess.STARTUPINFO()
184
- startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
185
- startupinfo.wShowWindow = subprocess.SW_HIDE
186
- startupinfo_options['startupinfo'] = startupinfo
187
-
188
- # Definindo stdout, stderr e stdin para DEVNULL para esconder saídas
189
- startupinfo_options['stdout'] = subprocess.DEVNULL
190
- startupinfo_options['stderr'] = subprocess.DEVNULL
191
- startupinfo_options['stdin'] = subprocess.DEVNULL
192
-
193
- elif system_user in ["Linux", "Darwin"]:
194
- # Para Linux e macOS, ocultar stdout, stderr e stdin
195
- startupinfo_options['stdout'] = subprocess.DEVNULL
196
- startupinfo_options['stderr'] = subprocess.DEVNULL
197
- startupinfo_options['stdin'] = subprocess.DEVNULL
198
-
199
- else:
200
- # Exceção para sistemas não suportados
201
- raise NotImplementedError(f"O sistema {system_user} não é suportado para ocultação de comandos.")
202
-
203
- return startupinfo_options