ffmpeg-for-python 0.3__tar.gz

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.
@@ -0,0 +1,5 @@
1
+ include README_PYPI
2
+
3
+ include ffmpeg_for_python/ffmpeg-bin/*.*
4
+
5
+
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: ffmpeg-for-python
3
+ Version: 0.3
4
+ Summary: Wrapper para o binário FFmpeg
5
+ Author: PauloCesar-dev404
6
+ Author-email: paulocesar0073dev404@gmail.com
7
+ License: MIT
8
+ Project-URL: Código Fonte, https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/ffmpeg_for_python-0.3.tar.gz
9
+ Project-URL: lib, https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/ffmpeg_for_python-0.3-py3-none-any.whl
10
+ Project-URL: GitHub, https://github.com/PauloCesar-dev404/ffmpeg-for-python
11
+ Project-URL: Bugs/Melhorias, https://github.com/PauloCesar-dev404/ffmpeg-for-python/issues
12
+ Project-URL: Documentação, https://github.com/PauloCesar-dev404/ffmpeg-for-python/wiki
13
+ Keywords: ffmpeg
14
+ Platform: any
15
+ Requires: requests
16
+ Description-Content-Type: text/markdown
17
+
18
+ # ffmpeg-for-python
19
+
20
+ Wrapper para o binário FFmpeg, permitindo o uso de comandos FFmpeg via Python. Para saber como usar FFmpeg, consulte a documentação no [site oficial](https://ffmpeg.org/ffmpeg.html)
21
+
22
+
23
+ ---
24
+
25
+
26
+ **conversão básica**
27
+ ```python
28
+
29
+ from ffmpeg_for_python import FFmpeg, FFmpegExceptions
30
+
31
+ # Cria uma instância do wrapper FFmpeg
32
+ ffmpeg = FFmpeg()
33
+ # Caminho do arquivo de entrada e saída
34
+ input_video = 'input_video.mp4'
35
+ output_video = 'output_video.mkv'
36
+
37
+ # Define o arquivo de entrada e o arquivo de saída
38
+ (ffmpeg
39
+ .overwrite_output # Sobrescrever se existir
40
+ .input(input_video) # Vídeo de entrada
41
+ .output(output_video) # Vídeo final
42
+ )
43
+
44
+ # Executa o comando FFmpeg e exibe a saída
45
+ try:
46
+ ffmpeg.run(capture_output=True)
47
+ except FFmpegExceptions as e:
48
+ print("Erro ao executar FFmpeg:", e)
49
+ ```
50
+ ---
51
+ **remux audio e video**
52
+ ```python
53
+ from ffmpeg_for_python import FFmpeg, FFmpegExceptions
54
+ # Cria uma instância do wrapper FFmpeg
55
+ ffmpeg = FFmpeg()
56
+ # Caminho dos arquivos de entrada e saída
57
+ input_video = 'input_video.mp4'
58
+ input_audio = 'input_audio.mp4'
59
+ output_video = 'output_video.mp4'
60
+ # Define os arquivos de entrada e o arquivo de saída
61
+ (ffmpeg
62
+ .overwrite_output # Sobrescrever se existir
63
+ .input(input_video) # Vídeo de entrada
64
+ .input(input_audio) # Áudio
65
+ .args(arguments=['-c:a', 'copy', '-c:v', 'copy']) # Parâmetros de cópia de áudio e vídeo
66
+ .output(output_video) # Vídeo final
67
+ )
68
+
69
+ # Executa o comando FFmpeg e exibe a saída
70
+ try:
71
+ ffmpeg.run(capture_output=True)
72
+ except FFmpegExceptions as e:
73
+ print("Erro ao executar FFmpeg:", e)
74
+ ```
75
+ ---
@@ -0,0 +1,15 @@
1
+
2
+ <div align="center">
3
+ <img src="assets/ffmpeg-for-python-logo.png" alt="ffmpeg-for-python-logo" width="200"/>
4
+
5
+
6
+
7
+ ![Versão](https://img.shields.io/badge/version-3.0-orange)
8
+ ![Licença](https://img.shields.io/badge/license-MIT-orange)
9
+ [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://apoia.se/paulocesar-dev404)
10
+
11
+ </div>
12
+
13
+ Wrapper para o binário FFmpeg, permitindo o uso de comandos FFmpeg via Python. Para saber como usar FFmpeg, consulte [a documentação no site oficial](https://ffmpeg.org/ffmpeg.html).
14
+
15
+ ---
@@ -0,0 +1,147 @@
1
+ import struct
2
+ import sys
3
+ import os
4
+ import requests
5
+ import zipfile
6
+ import shutil
7
+ import stat
8
+ from .exeptions import *
9
+ from .__utils import URL_PLATAFOMR,system
10
+
11
+ lib_name = 'ffmpeg_for_python'
12
+ URL_BASE_REPO = "https://raw.githubusercontent.com/PauloCesar-dev404/binarios/main/"
13
+
14
+
15
+
16
+
17
+ class Configurate:
18
+ """Configura variáveis de ambiente no ambiente virtual ou globalmente."""
19
+
20
+ def __init__(self):
21
+ self.VERSION = self.__read_version
22
+ self.FFMPEG_URL = os.getenv('FFMPEG_URL')
23
+ self.FFMPEG_BINARY = os.getenv('FFMPEG_BINARY')
24
+ PATH = os.path.join(self.is_venv, lib_name, 'ffmpeg-bin')
25
+ os.makedirs(PATH, exist_ok=True)
26
+ dirpath = PATH
27
+ self.INSTALL_DIR = os.getenv('INSTALL_DIR', dirpath)
28
+ self.VENV_PATH = os.getenv('VENV_PATH', self.INSTALL_DIR)
29
+ self.configure()
30
+
31
+ @property
32
+ def is_venv(self):
33
+ """Verifica se o script está sendo executado em um ambiente virtual e retorna o diretório de bibliotecas globais.
34
+ Se estiver em um ambiente virtual, retorna o diretório de bibliotecas do ambiente virtual. Caso contrário, retorna
35
+ o diretório de bibliotecas globais do Python global."""
36
+ if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
37
+ # Retorna o diretório de bibliotecas do ambiente virtual
38
+ return os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'Lib',
39
+ 'site-packages') if os.name == 'nt' else os.path.join \
40
+ (os.path.dirname(os.path.abspath(sys.executable)), 'lib',
41
+ 'python{0.major}.{0.minor}'.format(sys.version_info), 'site-packages')
42
+ else:
43
+ # Retorna o diretório de bibliotecas globais do Python global
44
+ return os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'Lib',
45
+ 'site-packages') if os.name == 'nt' else os.path.join \
46
+ (os.path.dirname(os.path.abspath(sys.executable)), 'lib',
47
+ 'python{0.major}.{0.minor}'.format(sys.version_info), 'site-packages')
48
+
49
+ def configure(self):
50
+ """Configura as variáveis de ambiente com base no sistema operacional."""
51
+ if not self.FFMPEG_URL or not self.FFMPEG_BINARY:
52
+ platform_name = system
53
+ if platform_name == 'Windows':
54
+ self.FFMPEG_URL = URL_PLATAFOMR
55
+ self.FFMPEG_BINARY = 'ffmpeg.exe'
56
+ elif platform_name == 'Linux':
57
+ self.FFMPEG_URL = URL_PLATAFOMR
58
+ self.FFMPEG_BINARY = 'ffmpeg'
59
+ else:
60
+ raise DeprecationWarning(f"Arquitetura '{platform_name}' ainda não suportada...\n\n"
61
+ f"Versão atual da lib: {self.VERSION}")
62
+ os.environ['FFMPEG_URL'] = self.FFMPEG_URL
63
+ os.environ['FFMPEG_BINARY'] = self.FFMPEG_BINARY
64
+
65
+ if not os.getenv('INSTALL_DIR'):
66
+ os.environ['INSTALL_DIR'] = self.INSTALL_DIR
67
+
68
+ @property
69
+ def __read_version(self):
70
+ """Lê a versão do arquivo __version__.py."""
71
+ version_file = os.path.join(os.path.dirname(os.path.abspath(__file__)).split('.')[0], '__version__.py')
72
+ if os.path.isfile(version_file):
73
+ with open(version_file, 'r') as file:
74
+ version_line = file.readline().strip()
75
+ if version_line.startswith('__version__'):
76
+ return version_line.split('=')[1].strip().strip("'")
77
+ return 'Unknown Version'
78
+
79
+ def __download_file(self, url: str, local_filename: str):
80
+ """Baixa um arquivo do URL para o caminho local especificado."""
81
+ try:
82
+ response = requests.get(url, stream=True)
83
+ response.raise_for_status()
84
+ total_length = int(response.headers.get('content-length', 0))
85
+
86
+ with open(local_filename, 'wb') as f:
87
+ start_time = time.time()
88
+ downloaded = 0
89
+
90
+ for data in response.iter_content(chunk_size=4096):
91
+ downloaded += len(data)
92
+ f.write(data)
93
+
94
+ elapsed_time = time.time() - start_time
95
+ elapsed_time = max(elapsed_time, 0.001)
96
+ speed_kbps = (downloaded / 1024) / elapsed_time
97
+ percent_done = (downloaded / total_length) * 100
98
+
99
+ sys.stdout.write(
100
+ f"\rBaixando Binários do ffmpeg: {percent_done:.2f}% | Velocidade: {speed_kbps:.2f} KB/s | "
101
+ f"Tempo decorrido: {int(elapsed_time)}s")
102
+ sys.stdout.flush()
103
+ sys.stdout.write("\nDownload completo.\n")
104
+ sys.stdout.flush()
105
+
106
+ except requests.RequestException as e:
107
+ raise Exception(f"Erro durante o download: {e}")
108
+
109
+ def __extract_zip(self, zip_path: str, extract_to: str):
110
+ """Descompacta o arquivo ZIP no diretório especificado."""
111
+ try:
112
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
113
+ zip_ref.extractall(extract_to)
114
+ except zipfile.BadZipFile as e:
115
+ sys.stderr.write(f"Erro ao descompactar o arquivo: {e}\n")
116
+ raise
117
+ finally:
118
+ os.remove(zip_path)
119
+
120
+ def remove_file(self, file_path: str):
121
+ """Remove o arquivo ou diretório especificado."""
122
+ if os.path.exists(file_path):
123
+ try:
124
+ shutil.rmtree(file_path, onerror=self.handle_remove_readonly)
125
+ except Exception as e:
126
+ print(f"Erro ao remover {file_path}: {e}")
127
+ raise
128
+
129
+ def install_bins(self):
130
+ """Instala o ffmpeg baixando e descompactando o binário apropriado."""
131
+ zip_path = os.path.join(self.INSTALL_DIR, "ffmpeg.zip")
132
+ os.makedirs(self.INSTALL_DIR, exist_ok=True)
133
+ self.__download_file(self.FFMPEG_URL, zip_path)
134
+ self.__extract_zip(zip_path, self.INSTALL_DIR)
135
+ self.remove_file(zip_path)
136
+ bina = os.path.join(self.INSTALL_DIR, self.FFMPEG_BINARY)
137
+ os.environ["PATH"] += os.pathsep + self.INSTALL_DIR
138
+ return
139
+
140
+ def handle_remove_readonly(self, func, path, exc_info):
141
+ """Callback para lidar com arquivos somente leitura."""
142
+ os.chmod(path, stat.S_IWRITE)
143
+ func(path)
144
+
145
+
146
+ if __name__ == "__main__":
147
+ FFmpegExceptions("erro de runtime...")
@@ -0,0 +1,8 @@
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!")
@@ -0,0 +1,78 @@
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!")
@@ -0,0 +1,6 @@
1
+ __version__ = '0.3'
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'
@@ -0,0 +1,91 @@
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
+
@@ -0,0 +1,178 @@
1
+ import os
2
+ import platform
3
+ import subprocess
4
+ import time
5
+ from typing import List, Optional
6
+ from .exeptions import wraper_erros, FFmpegExceptions
7
+ from .__config__ import Configurate
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 padrão e de erro.
49
+
50
+ Returns:
51
+ Optional[str]: A saída do comando, se capturada. Caso contrário, None.
52
+ """
53
+
54
+ configs = self.__oculte_comands_your_system.get('startupinfo')
55
+ # Armazenar a saída completa, se for necessário capturá-la
56
+ output = []
57
+
58
+ # Executa o comando utilizando subprocess
59
+ with subprocess.Popen(
60
+ self.__command,
61
+ startupinfo=configs,
62
+ stdout=subprocess.PIPE,
63
+ stderr=subprocess.PIPE,
64
+ stdin=subprocess.PIPE,
65
+ text=True,
66
+ bufsize=1, # Linha por linha
67
+ universal_newlines=True # Garante que novas linhas sejam interpretadas corretamente
68
+ ) as process:
69
+ # Lê a saída de erro padrão (stderr) em tempo real
70
+ for linha in process.stderr:
71
+ time.sleep(0.01)
72
+ linha_filtrada = wraper_erros(linha)
73
+ if linha_filtrada:
74
+ process.terminate()
75
+ raise FFmpegExceptions(message=f'Erro na execução do ffmpeg: "{linha_filtrada}"')
76
+ else:
77
+ if capture_output:
78
+ print(linha.strip())
79
+
80
+ # Espera o processo terminar e captura a saída padrão (stdout)
81
+ stdout, stderr = process.communicate()
82
+
83
+ if capture_output:
84
+ output.extend(stdout.splitlines())
85
+ return '\n'.join(output)
86
+ else:
87
+ return stdout.strip() if stdout else None
88
+
89
+ def input(self, file_path: str) -> 'FFmpeg':
90
+ """Define o arquivo de entrada para o FFmpeg."""
91
+ cmd = ['-i', file_path]
92
+ self.args(cmd)
93
+ return self
94
+
95
+ def output(self, output_path: str) -> 'FFmpeg':
96
+ """Define o arquivo de saída para o FFmpeg e verifica se a sobrescrita está permitida."""
97
+ if os.path.exists(output_path):
98
+ if not self.__overwrite_output:
99
+ raise FFmpegExceptions(f"O arquivo de saída '{output_path}' já existe! Use 'overwrite_output' para "
100
+ f"sobrescrevê-lo.")
101
+
102
+ # Adiciona o arquivo de saída ao comando
103
+ cmd = [output_path]
104
+ self.args(cmd)
105
+ return self
106
+
107
+ @property
108
+ def overwrite_output(self):
109
+ """
110
+ Adiciona o parâmetro '-y' ao comando FFmpeg, o que permite sobrescrever o arquivo de saída
111
+ caso ele já exista.
112
+
113
+ Importante: Esta propriedade deve ser definida antes dos parâmetros de entrada e saída
114
+ para garantir que o comando FFmpeg seja construído corretamente. Caso contrário, o comando
115
+ pode não ser executado como esperado.
116
+
117
+ Returns:
118
+ FFmpeg: Retorna a instância atual para encadeamento de métodos.
119
+ """
120
+ self.__overwrite_output = True
121
+ cmd = ['-y']
122
+ self.args(cmd)
123
+ return self
124
+
125
+ @property
126
+ def copy(self) -> 'FFmpeg':
127
+ """Adiciona o parâmetro '-c copy' ao comando FFm"""
128
+ self.__command.extend(['-c', 'copy'])
129
+ return self
130
+
131
+ @property
132
+ def reset(self) -> 'FFmpeg':
133
+ """Reseta o comando para reutilização do objeto."""
134
+ self.__command = [self.__ffmpeg_path]
135
+ return self
136
+
137
+ @staticmethod
138
+ def __verify_path(bin_path, path_type: str) -> bool:
139
+ """
140
+ Verifica se um caminho de arquivo ou diretório existe.
141
+
142
+ Args:
143
+ bin_path : O caminho a ser verificado.
144
+ path_type (str): O tipo de caminho ('file' para arquivo, 'dir' para diretório).
145
+
146
+ Returns:
147
+ bool: True se o caminho existir e for do tipo especificado, False caso contrário.
148
+ """
149
+ if path_type == 'file':
150
+ return os.path.isfile(bin_path)
151
+ elif path_type == 'dir':
152
+ return os.path.isdir(bin_path)
153
+ else:
154
+ raise ValueError("Invalid path_type. Use 'file' or 'dir'.")
155
+
156
+ @property
157
+ def __oculte_comands_your_system(self):
158
+ """Identifica o sistema do usuário e cria um dicionário de parâmetros para ocultar saídas de janelas."""
159
+ system_user = platform.system()
160
+ startupinfo_options = {}
161
+
162
+ if system_user == "Windows":
163
+ startupinfo = subprocess.STARTUPINFO()
164
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
165
+ startupinfo.wShowWindow = subprocess.SW_HIDE
166
+ startupinfo_options['startupinfo'] = startupinfo
167
+
168
+ elif system_user in ["Linux", "Darwin"]:
169
+ startupinfo_options['stdout'] = subprocess.DEVNULL
170
+ startupinfo_options['stderr'] = subprocess.DEVNULL
171
+ startupinfo_options['stdin'] = subprocess.DEVNULL
172
+
173
+ else:
174
+ raise NotImplementedError(f"System {system_user} not supported")
175
+
176
+ return startupinfo_options
177
+
178
+
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: ffmpeg-for-python
3
+ Version: 0.3
4
+ Summary: Wrapper para o binário FFmpeg
5
+ Author: PauloCesar-dev404
6
+ Author-email: paulocesar0073dev404@gmail.com
7
+ License: MIT
8
+ Project-URL: Código Fonte, https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/ffmpeg_for_python-0.3.tar.gz
9
+ Project-URL: lib, https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/ffmpeg_for_python-0.3-py3-none-any.whl
10
+ Project-URL: GitHub, https://github.com/PauloCesar-dev404/ffmpeg-for-python
11
+ Project-URL: Bugs/Melhorias, https://github.com/PauloCesar-dev404/ffmpeg-for-python/issues
12
+ Project-URL: Documentação, https://github.com/PauloCesar-dev404/ffmpeg-for-python/wiki
13
+ Keywords: ffmpeg
14
+ Platform: any
15
+ Requires: requests
16
+ Description-Content-Type: text/markdown
17
+
18
+ # ffmpeg-for-python
19
+
20
+ Wrapper para o binário FFmpeg, permitindo o uso de comandos FFmpeg via Python. Para saber como usar FFmpeg, consulte a documentação no [site oficial](https://ffmpeg.org/ffmpeg.html)
21
+
22
+
23
+ ---
24
+
25
+
26
+ **conversão básica**
27
+ ```python
28
+
29
+ from ffmpeg_for_python import FFmpeg, FFmpegExceptions
30
+
31
+ # Cria uma instância do wrapper FFmpeg
32
+ ffmpeg = FFmpeg()
33
+ # Caminho do arquivo de entrada e saída
34
+ input_video = 'input_video.mp4'
35
+ output_video = 'output_video.mkv'
36
+
37
+ # Define o arquivo de entrada e o arquivo de saída
38
+ (ffmpeg
39
+ .overwrite_output # Sobrescrever se existir
40
+ .input(input_video) # Vídeo de entrada
41
+ .output(output_video) # Vídeo final
42
+ )
43
+
44
+ # Executa o comando FFmpeg e exibe a saída
45
+ try:
46
+ ffmpeg.run(capture_output=True)
47
+ except FFmpegExceptions as e:
48
+ print("Erro ao executar FFmpeg:", e)
49
+ ```
50
+ ---
51
+ **remux audio e video**
52
+ ```python
53
+ from ffmpeg_for_python import FFmpeg, FFmpegExceptions
54
+ # Cria uma instância do wrapper FFmpeg
55
+ ffmpeg = FFmpeg()
56
+ # Caminho dos arquivos de entrada e saída
57
+ input_video = 'input_video.mp4'
58
+ input_audio = 'input_audio.mp4'
59
+ output_video = 'output_video.mp4'
60
+ # Define os arquivos de entrada e o arquivo de saída
61
+ (ffmpeg
62
+ .overwrite_output # Sobrescrever se existir
63
+ .input(input_video) # Vídeo de entrada
64
+ .input(input_audio) # Áudio
65
+ .args(arguments=['-c:a', 'copy', '-c:v', 'copy']) # Parâmetros de cópia de áudio e vídeo
66
+ .output(output_video) # Vídeo final
67
+ )
68
+
69
+ # Executa o comando FFmpeg e exibe a saída
70
+ try:
71
+ ffmpeg.run(capture_output=True)
72
+ except FFmpegExceptions as e:
73
+ print("Erro ao executar FFmpeg:", e)
74
+ ```
75
+ ---
@@ -0,0 +1,16 @@
1
+ MANIFEST.in
2
+ README.md
3
+ setup.py
4
+ assets/ffmpeg-for-python-logo.png
5
+ ffmpeg_for_python/__config__.py
6
+ ffmpeg_for_python/__init__.py
7
+ ffmpeg_for_python/__utils.py
8
+ ffmpeg_for_python/__version__.py
9
+ ffmpeg_for_python/exeptions.py
10
+ ffmpeg_for_python/ffmpeg.py
11
+ ffmpeg_for_python.egg-info/PKG-INFO
12
+ ffmpeg_for_python.egg-info/SOURCES.txt
13
+ ffmpeg_for_python.egg-info/dependency_links.txt
14
+ ffmpeg_for_python.egg-info/not-zip-safe
15
+ ffmpeg_for_python.egg-info/top_level.txt
16
+ ffmpeg_for_python/ffmpeg-bin/readme.md
@@ -0,0 +1 @@
1
+ ffmpeg_for_python
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,54 @@
1
+ import os.path
2
+ import re
3
+ from ffmpeg_for_python.__config__ import Configurate
4
+ from ffmpeg_for_python.__version__ import __version__, __autor__, __repo__, __source__, __lib__
5
+ from setuptools import setup, find_packages
6
+ cached = os.path.join('ffmpeg_for_python', '__pycache__')
7
+ libs_ = os.path.join('dist')
8
+ # Regex para capturar a versão do arquivo
9
+ # Regex para capturar a versão do arquivo tanto para .tar.gz quanto para .whl
10
+ version_regex = re.compile(r'ffmpeg_for_python-(\d+\.\d+\.\d+)(?:-py3-none-any)?\.(?:tar\.gz|whl)')
11
+ # Remover o cache do __pycache__ se existir
12
+ if os.path.exists(cached):
13
+ c = Configurate()
14
+ c.remove_file(file_path=cached)
15
+ # Remover pacotes antigos da pasta dist, se a versão for diferente da atual
16
+ if os.path.exists(libs_):
17
+ for file_name in os.listdir(libs_):
18
+ match = version_regex.match(file_name)
19
+ if match:
20
+ file_version = match.group(1)
21
+ if file_version != __version__:
22
+ file_path = os.path.join(libs_, file_name)
23
+ os.remove(file_path)
24
+ print(f'Removido {file_name} com versão {file_version}')
25
+
26
+ # Lê o conteúdo do README.md
27
+ with open('README_PYPI.md', 'r', encoding='utf-8') as file:
28
+ long_description = file.read()
29
+
30
+ setup(
31
+ name="ffmpeg-for-python",
32
+ version=__version__,
33
+ description="Wrapper para o binário FFmpeg",
34
+ long_description=long_description,
35
+ long_description_content_type="text/markdown",
36
+ author=__autor__,
37
+ author_email="paulocesar0073dev404@gmail.com",
38
+ license="MIT",
39
+ keywords=["ffmpeg"],
40
+ requires=['requests'],
41
+ packages=find_packages(),
42
+ package_data={"ffmpeg_for_python.ffmpeg-bin": ["*.*"]},
43
+ zip_safe=False,
44
+ include_package_data=True,
45
+ platforms=["any"],
46
+ project_urls={
47
+ "Código Fonte": __source__,
48
+ "lib": __lib__,
49
+ 'GitHub': __repo__,
50
+ "Bugs/Melhorias": f"{__repo__}/issues",
51
+ "Documentação": f"{__repo__}/wiki",
52
+ },
53
+
54
+ )