|
13 | 13 | import urllib.request |
14 | 14 | import webbrowser |
15 | 15 | from pathlib import Path |
| 16 | +import zipfile |
| 17 | +import shutil |
16 | 18 |
|
17 | 19 | try: |
18 | 20 | import ffmpeg as ffmpeg_lib # optional: ffmpeg-python |
@@ -45,6 +47,18 @@ def load_config(file_name): |
45 | 47 | config.read(file_name) |
46 | 48 | apply_saved_config() |
47 | 49 |
|
| 50 | +def load_config_from_file(): |
| 51 | + path = filedialog.askopenfilename(title="Carregar Configuração", filetypes=[("Arquivos INI", "*.ini")]) |
| 52 | + if not path: |
| 53 | + return |
| 54 | + try: |
| 55 | + config.read(path) |
| 56 | + apply_saved_config() |
| 57 | + messagebox.showinfo('Configuração', f'Configuração carregada de {path}') |
| 58 | + except Exception as e: |
| 59 | + messagebox.showerror('Erro', f'Falha ao carregar configuração: {e}') |
| 60 | + |
| 61 | + |
48 | 62 | def save_config(): |
49 | 63 | config_file_path = filedialog.asksaveasfilename(initialdir=os.getcwd(), title="Salvar Configuração", defaultextension=".ini", |
50 | 64 | filetypes=[("Arquivos INI", "*.ini")]) |
@@ -143,29 +157,84 @@ def select_ffmpeg_executable(): |
143 | 157 | update_command_display() |
144 | 158 |
|
145 | 159 |
|
| 160 | +def _extract_ffmpeg_zip(zip_path, target_bin_dir): |
| 161 | + """Extract ffmpeg binary from the downloaded zip into target_bin_dir. |
| 162 | + Returns path to extracted ffmpeg executable if found, else None.""" |
| 163 | + try: |
| 164 | + with zipfile.ZipFile(zip_path, 'r') as zf: |
| 165 | + # Extract all to a temporary folder and search for ffmpeg/ffmpeg.exe |
| 166 | + temp_dir = target_bin_dir.parent / ("ffmpeg_tmp") |
| 167 | + if temp_dir.exists(): |
| 168 | + shutil.rmtree(temp_dir) |
| 169 | + temp_dir.mkdir(parents=True, exist_ok=True) |
| 170 | + zf.extractall(path=temp_dir) |
| 171 | + |
| 172 | + # Walk extracted tree and find ffmpeg executable |
| 173 | + exe_name = 'ffmpeg.exe' if os.name == 'nt' else 'ffmpeg' |
| 174 | + found = None |
| 175 | + for root, dirs, files in os.walk(temp_dir): |
| 176 | + if exe_name in files: |
| 177 | + found = Path(root) / exe_name |
| 178 | + break |
| 179 | + if not found: |
| 180 | + # Try common structure 'ffmpeg-*/bin/ffmpeg' |
| 181 | + for root, dirs, files in os.walk(temp_dir): |
| 182 | + for d in dirs: |
| 183 | + p = Path(root) / d / 'bin' / exe_name |
| 184 | + if p.exists(): |
| 185 | + found = p |
| 186 | + break |
| 187 | + if found: |
| 188 | + break |
| 189 | + if found: |
| 190 | + target_bin_dir.mkdir(parents=True, exist_ok=True) |
| 191 | + target_path = target_bin_dir / exe_name |
| 192 | + shutil.copy2(found, target_path) |
| 193 | + # ensure executable bit on non-Windows |
| 194 | + if os.name != 'nt': |
| 195 | + target_path.chmod(0o755) |
| 196 | + # cleanup temp |
| 197 | + shutil.rmtree(temp_dir) |
| 198 | + return str(target_path) |
| 199 | + else: |
| 200 | + shutil.rmtree(temp_dir) |
| 201 | + return None |
| 202 | + except Exception: |
| 203 | + return None |
| 204 | + |
| 205 | + |
146 | 206 | def download_ffmpeg_and_maybe_install(): |
147 | 207 | """Download a FFmpeg build to the user's Downloads folder. |
148 | | - On Windows offer to try winget install if available and the user agrees. |
149 | | - Runs in a background thread to avoid blocking the UI.""" |
| 208 | + On Windows: download zip, extract ffmpeg into ./bin and optionally try winget install. |
| 209 | + On non-Windows: open releases page in browser. Runs in background thread.""" |
150 | 210 | def _worker(): |
151 | 211 | try: |
152 | 212 | downloads = Path.home() / 'Downloads' |
153 | 213 | downloads.mkdir(parents=True, exist_ok=True) |
154 | 214 | if os.name == 'nt': |
155 | | - # Example Windows build (user-provided example) |
| 215 | + # Example Windows build URL (may be updated if releases change) |
156 | 216 | url = 'https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-win64-gpl-7.1.zip' |
157 | 217 | out_path = downloads / url.split('/')[-1] |
158 | 218 | messagebox.showinfo('Download', f'Baixando FFmpeg para {out_path} ...') |
159 | 219 | urllib.request.urlretrieve(url, out_path) |
160 | | - messagebox.showinfo('Download', f'Arquivo salvo em {out_path}') |
| 220 | + # Extract into repo's bin/ folder |
| 221 | + target_bin = Path(os.path.dirname(os.path.abspath(__file__))) / 'bin' |
| 222 | + extracted = _extract_ffmpeg_zip(out_path, target_bin) |
| 223 | + if extracted: |
| 224 | + messagebox.showinfo('Download', f'FFmpeg extraído para {extracted}. Atualizando caminho...') |
| 225 | + ffmpeg_path_entry.delete(0, tk.END) |
| 226 | + ffmpeg_path_entry.insert(0, extracted) |
| 227 | + config['DEFAULT']['ffmpeg_path'] = extracted |
| 228 | + with open(config_file, 'w') as configfile: |
| 229 | + config.write(configfile) |
| 230 | + else: |
| 231 | + messagebox.showwarning('Download', f'Não foi possível extrair o executável FFmpeg automaticamente. O arquivo está em {out_path}') |
161 | 232 |
|
162 | 233 | # Ask user if they want to attempt installation via winget |
163 | 234 | if messagebox.askyesno('Instalar', 'Deseja tentar instalar via winget (Windows)?'): |
164 | 235 | try: |
165 | | - # Check winget availability |
166 | 236 | res = subprocess.run(['winget', '--version'], capture_output=True, text=True) |
167 | 237 | if res.returncode == 0: |
168 | | - # Try a generic winget install for ffmpeg |
169 | 238 | install_cmd = ['winget', 'install', 'ffmpeg', '-e'] |
170 | 239 | proc = subprocess.run(install_cmd, capture_output=True, text=True) |
171 | 240 | if proc.returncode == 0: |
|
0 commit comments