Metadata-Version: 2.4
Name: dailymotionx
Version: 0.2.1
Summary: Download Dailymotion videos from episode pages or direct links — CLI, Python API, and browser UI
Author-email: Shyam Darshanam <shyamdarshanam17@gmail.com>
Maintainer-email: Shyam Darshanam <shyamdarshanam17@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/shyamdarshanam/embed-downloader
Project-URL: Source, https://github.com/shyamdarshanam/embed-downloader
Project-URL: Bug Tracker, https://github.com/shyamdarshanam/embed-downloader/issues
Project-URL: Changelog, https://github.com/shyamdarshanam/embed-downloader/releases
Keywords: dailymotion,downloader,yt-dlp,video,cli,anime,myanime,episode,stream,mp4,ffmpeg,web-ui,browser-ui,embed
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: yt-dlp>=2026.3.17
Requires-Dist: rich>=13.7.1
Requires-Dist: questionary>=2.0.1
Provides-Extra: impersonate
Requires-Dist: curl-cffi<0.15,>=0.10; extra == "impersonate"
Provides-Extra: dev
Requires-Dist: pytest>=8.2; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: build>=1.2.2; extra == "dev"
Requires-Dist: twine>=5.1.1; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"
Requires-Dist: mypy>=1.10.0; extra == "dev"
Dynamic: license-file

# dailymotionx

[![PyPI version](https://img.shields.io/pypi/v/dailymotionx.svg?color=blue&label=PyPI)](https://pypi.org/project/dailymotionx/)
[![Python](https://img.shields.io/pypi/pyversions/dailymotionx.svg)](https://pypi.org/project/dailymotionx/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![OS](https://img.shields.io/badge/OS-Windows%20%7C%20macOS%20%7C%20Linux-informational)](https://pypi.org/project/dailymotionx/)

**Download Dailymotion videos from episode pages or direct links — via CLI, Python API, or a local browser UI.**

Designed for sites like [myanime.live](https://myanime.live) that embed Dailymotion players, but works with any page that contains a Dailymotion player URL, as well as direct `dailymotion.com` and `dai.ly` links.

---

## Features

- 🌐 **Browser UI** — launch a beautiful local web app (`dailymotion ui`), no terminal intimidation
- ⌨️ **Interactive CLI** — guided prompts for URL and resolution using `questionary` + `rich`
- 🔗 **Episode page support** — paste a myanime.live (or similar) URL and the Dailymotion embed is extracted automatically
- 📺 **All Dailymotion URL formats** — embed, player, watch, short link
- 🎞️ **Merged MP4 output** — video + audio merged to a single `.mp4` via `ffmpeg`
- 📊 **Real-time progress** — animated progress bar in the browser UI; rich progress in CLI
- 🔔 **yt-dlp update alerts** — notifies you if a newer yt-dlp is on PyPI (never auto-updates silently)
- 🩺 **Doctor command** — check all dependencies at a glance
- 🖥️ **Cross-platform** — Windows, macOS, Linux; browser impersonation via `curl-cffi`
- 🐍 **Python API** — import and use as a library in your own scripts

---

## Requirements

| Requirement | Notes |
|-------------|-------|
| Python ≥ 3.10 | |
| `ffmpeg` | Must be on PATH — used for audio/video merge |
| `yt-dlp` | Installed automatically as a dependency |

### Installing ffmpeg

**Linux (Debian/Ubuntu)**
```bash
sudo apt update && sudo apt install -y ffmpeg
```

**macOS**
```bash
brew install ffmpeg
```

**Windows**
```powershell
winget install Gyan.FFmpeg
```

Or download from [ffmpeg.org](https://ffmpeg.org/download.html).

---

## Installation

```bash
pip install dailymotionx
```

The `dailymotion` command will be available immediately after install.

---

## Quick Start

### Browser UI (recommended for beginners)

```bash
dailymotion ui
```

Opens a local web page automatically. Paste your URL, pick a resolution, click **Download**. That's it.

### Interactive CLI

```bash
dailymotion
```

The CLI will prompt you for the URL and resolution.

### One-liner

```bash
dailymotion "https://myanime.live/some-episode-page/" --resolution 720
```

---

## CLI Reference

### `dailymotion download`

```
dailymotion [download] [URL] [OPTIONS]
```

The `download` subcommand is the default — you can omit it entirely.

| Option | Default | Description |
|--------|---------|-------------|
| `URL` | *(interactive prompt)* | Episode page URL or direct Dailymotion URL |
| `-r`, `--resolution` | `720` | Target resolution: `360`, `480`, `720`, `1080`, `best` |
| `-o`, `--output-dir` | `~/Downloads` | Directory to save the MP4 |
| `-c`, `--concurrency` | `12` | Number of parallel fragment downloads |
| `--timeout` | `35` | HTTP timeout in seconds |
| `--non-interactive` | `False` | Fail instead of prompting for missing inputs |

**Examples:**

```bash
# Interactive (prompts for URL and resolution)
dailymotion

# Episode page URL
dailymotion "https://myanime.live/2026/04/19/battle-through-the-heavens-season-5-episode-195-english-sub/"

# Direct Dailymotion link
dailymotion "https://www.dailymotion.com/video/k4YiCNzUwtjazkFAmg2" -r 1080

# Save to specific folder, non-interactive
dailymotion "https://dai.ly/k4YiCNzUwtjazkFAmg2" -r best -o ~/Videos --non-interactive
```

---

### `dailymotion ui`

```
dailymotion ui [--port PORT] [--no-browser]
```

Starts a local HTTP server and opens the browser UI automatically.

| Option | Default | Description |
|--------|---------|-------------|
| `--port` | `0` (auto) | Port to listen on |
| `--no-browser` | `False` | Don't open the browser automatically |

The UI features:
- Real-time animated progress bar with phase indicators (Resolving → Video → Audio → Merging → Done)
- Live speed and ETA display
- Collapsible detailed log
- yt-dlp update banner if a newer version is on PyPI
- ffmpeg missing warning with install instructions

---

### `dailymotion doctor`

```
dailymotion doctor [--upgrade-ytdlp]
```

Checks all runtime dependencies and prints their status:

```
╭────────────── Doctor ──────────────╮
│ Dependency check results           │
╰────────────────────────────────────╯
  - yt-dlp:     OK (available)
  - rich:       OK (available)
  - questionary:OK (available)
  - curl-cffi:  OK (available)
  - ffmpeg:     OK (available)

yt-dlp is up to date.
```

| Option | Description |
|--------|-------------|
| `--upgrade-ytdlp` | Run `pip install --upgrade yt-dlp` during this check |

---

### yt-dlp update notifications

`dailymotionx` checks PyPI for a newer version of `yt-dlp` at startup and prints a one-line notice if one is found. It **never** installs updates silently.

```
yt-dlp update available (2026.3.17 → 2026.6.1). Run: pip install --upgrade yt-dlp
```

Use `dailymotion doctor --upgrade-ytdlp` when you're ready to upgrade.

---

## Supported URL Formats

| Format | Example |
|--------|---------|
| myanime.live episode page | `https://myanime.live/2026/.../episode-name/` |
| Any page with embedded Dailymotion | `https://example.com/episode` |
| Dailymotion watch link | `https://www.dailymotion.com/video/k4Yi...` |
| Dailymotion embed | `https://www.dailymotion.com/embed/video/k4Yi...` |
| Dailymotion geo player | `https://geo.dailymotion.com/player.html?video=k4Yi...` |
| Short link | `https://dai.ly/k4Yi...` |

---

## Python API

```python
from pathlib import Path
from dailymotionx import DownloadRequest, download_episode

request = DownloadRequest(
    episode_url="https://myanime.live/2026/04/19/battle-through-the-heavens-s5-ep195-english-sub/",
    resolution="720",
    output_dir=Path.home() / "Downloads",
    concurrency=12,
    timeout_seconds=35,
)

result = download_episode(request)
print(f"Saved to: {result.output_file}")
```

### Resolve only (no download)

```python
from dailymotionx import resolve_episode_page, resolve_input_url

# From an episode page
dm_url = resolve_episode_page("https://myanime.live/some-episode/")
print(dm_url)  # https://geo.dailymotion.com/player.html?video=...

# From any supported URL (episode page or direct DM link)
dm_url = resolve_input_url("https://www.dailymotion.com/video/abc123")
print(dm_url)  # https://geo.dailymotion.com/player.html?video=abc123
```

### Using progress hooks

```python
def my_hook(d: dict) -> None:
    if d["status"] == "downloading":
        pct = d.get("downloaded_bytes", 0) / (d.get("total_bytes") or 1) * 100
        print(f"\r{pct:.1f}%", end="", flush=True)

result = download_episode(request, progress_hooks=[my_hook])
```

---

## Output Files

Files are saved as:
```
{title} [{video_id}].mp4
```

Filenames are sanitised for cross-platform compatibility (`restrictfilenames`, `windowsfilenames`).

**Output directory priority:**
1. `--output-dir` / `output_dir` argument
2. `~/Downloads` (if writable)
3. Current working directory

---

## Dependency Notes

| Package | Role |
|---------|------|
| `yt-dlp` | Video extraction and download engine |
| `curl-cffi` | Browser-impersonating HTTP client (cross-platform TLS fingerprinting) |
| `rich` | Beautiful terminal output |
| `questionary` | Interactive CLI prompts |
| `ffmpeg` *(system)* | Audio/video stream merging (must be installed separately) |

`curl-cffi` enables browser TLS impersonation on all platforms — no manual setup needed beyond `pip install dailymotionx`.

---

## Development

```bash
git clone https://github.com/shyamdarshanam/embed-downloader
cd embed-downloader
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
```

**Run tests:**
```bash
pytest
```

**Lint:**
```bash
ruff check src/
```

**Type check:**
```bash
mypy src/dailymotionx/
```

**Build package:**
```bash
python -m build
twine check dist/*
```

**Publish to PyPI:**
```bash
twine upload dist/*
```

---

## License

MIT — see [LICENSE](LICENSE).
