What makes us different from other similar websites? › Forums › Tech › Professional Media Downloader
Tagged: Download Video, Download Video Website, Media Downloader, video downloader, Website Video Downloader
- This topic has 0 replies, 1 voice, and was last updated 2 weeks ago by
thumbtak.
Viewing 1 post (of 1 total)
-
AuthorPosts
-
June 2, 2026 at 10:43 pm #8490
thumbtakModeratorI was bored and decided to make an app that can download m3u8 files from any website, and save it as mp4. All you need to do is grab the m3u8 link from the website, by copying the link in the video player, or by using F12 to grab the link.
Save these two files in a folder and run
python3 bootstrap.py. This will download all the files into a temp container.Note: This application is in beta, and hasn’t been long term tested. Use at your own risk.
app.py
import sys import re import yt_dlp from PySide6.QtCore import QThread, Signal, Qt from PySide6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QLineEdit, QPushButton, QTableWidget, QTableWidgetItem, QWidget, QHBoxLayout, QHeaderView, QLabel) from PySide6.QtGui import QFont class DownloadWorker(QThread): status_update = Signal(int, str) def __init__(self, row, url, filename): super().__init__() self.row = row self.url = url self.filename = filename def run(self): self.ansi_escape = re.compile(r'\x1b\[[0-9;]*m') ydl_opts = { 'progress_hooks': [self.hook], 'outtmpl': f'./downloads/{self.filename}.%(ext)s', 'format': 'best', 'merge_output_format': 'mp4' } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([self.url]) self.status_update.emit(self.row, "✓ Completed") except Exception: self.status_update.emit(self.row, "⚠ Error") def hook(self, d): if d['status'] == 'downloading': raw_p = d.get('_percent_str', '0%') clean_p = self.ansi_escape.sub('', raw_p).strip() self.status_update.emit(self.row, f"Downloading: {clean_p}") class DownloaderApp(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Professional Media Downloader") self.setMinimumSize(850, 550) # Pink Theme Stylesheet self.setStyleSheet(""" QMainWindow { background-color: #1e1e1e; } QLineEdit { padding: 12px; border: 1px solid #333; border-radius: 6px; color: #e0e0e0; background: #2d2d2d; font-size: 14px; } QPushButton { padding: 10px 20px; background-color: #e91e63; color: white; border-radius: 6px; font-weight: bold; border: none; } QPushButton:hover { background-color: #c2185b; } QTableWidget { background-color: #252526; color: #d4d4d4; gridline-color: #333; selection-background-color: #880e4f; } QHeaderView::section { background-color: #333; color: #fff; padding: 8px; border: none; } QLabel#HeaderLabel { color: #e91e63; font-weight: bold; } """) self.workers = [] main_widget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(20, 20, 20, 20) # Header header = QLabel("Add New Download Task") header.setObjectName("HeaderLabel") layout.addWidget(header) # Input Area input_layout = QHBoxLayout() self.url_input = QLineEdit(placeholderText="Paste URL here...") self.name_input = QLineEdit(placeholderText="Filename...") self.btn = QPushButton("Start Download") input_layout.addWidget(self.url_input, stretch=3) input_layout.addWidget(self.name_input, stretch=1) input_layout.addWidget(self.btn) layout.addLayout(input_layout) # Table self.table = QTableWidget(0, 3) self.table.setHorizontalHeaderLabels(["URL", "Filename", "Status"]) self.table.horizontalHeader().setStretchLastSection(True) layout.addWidget(self.table) # Clickable Pink Footer footer = QLabel('<a href="https://taksshack.com/members/thumbtak/" style="color: #e91e63; text-decoration: none;">Created by thumbtak @ https://taksshack.com/members/thumbtak/</a>') footer.setAlignment(Qt.AlignCenter) footer.setOpenExternalLinks(True) footer.setStyleSheet("font-size: 11px; margin-top: 10px;") layout.addWidget(footer) main_widget.setLayout(layout) self.setCentralWidget(main_widget) self.btn.clicked.connect(self.add_task) def add_task(self): row = self.table.rowCount() self.table.insertRow(row) self.table.setItem(row, 0, QTableWidgetItem(self.url_input.text())) self.table.setItem(row, 1, QTableWidgetItem(self.name_input.text())) self.table.setItem(row, 2, QTableWidgetItem("Initializing...")) worker = DownloadWorker(row, self.url_input.text(), self.name_input.text()) worker.status_update.connect(lambda r, s: self.table.setItem(r, 2, QTableWidgetItem(s))) self.workers.append(worker) worker.start() self.url_input.clear() self.name_input.clear() def closeEvent(self, event): for worker in self.workers: if worker.isRunning(): worker.terminate() worker.wait() event.accept() if __name__ == "__main__": app = QApplication(sys.argv) app.setFont(QFont("Segoe UI", 10)) window = DownloaderApp() window.show() sys.exit(app.exec())bootstrap.py
import os import subprocess import venv import shutil VENV_DIR = ".temp_env" def setup(): if not os.path.exists(VENV_DIR): print("Creating temporary environment...") venv.create(VENV_DIR, with_pip=True) pip_path = os.path.join(VENV_DIR, 'bin', 'pip') python_path = os.path.join(VENV_DIR, 'bin', 'python') print("Installing dependencies...") subprocess.check_call([pip_path, "install", "yt-dlp", "PySide6"]) print("Launching application...") try: subprocess.call([python_path, "app.py"]) finally: print("Cleaning up environment...") if os.path.exists(VENV_DIR): shutil.rmtree(VENV_DIR) if __name__ == "__main__": setup() -
AuthorPosts
Viewing 1 post (of 1 total)
- You must be logged in to reply to this topic.
