Metadata-Version: 2.4
Name: java2-extention
Version: 1.0.8
Summary: Async video downloader with Cloudflare bypass, parallel chunked transfers, and multi-source HTML extraction. Termux / ARMv7 optimised.
License: MIT
Project-URL: Homepage, https://pypi.org/project/java2-extention/
Keywords: video,downloader,cloudflare,async,termux,aiohttp
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Multimedia :: Video
Classifier: Environment :: Console
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: cloudscraper>=1.2.60
Requires-Dist: requests>=2.28.0
Provides-Extra: fast
Requires-Dist: lxml>=5.0.0; extra == "fast"
Requires-Dist: aiodns>=3.0.0; extra == "fast"
Requires-Dist: brotli>=1.0.9; extra == "fast"

# java2-extention

Async video downloader with Cloudflare bypass, parallel chunked transfers,
and multi-source HTML extraction.  
**Optimised for Termux / ARMv7 / 2 GB RAM.**

---

## Install

```bash
pip install java2-extention
```

With faster optional deps (lxml, aiodns, brotli):

```bash
pip install "java2-extention[fast]"
```

### Termux one-liner

```bash
pkg update && pkg install python python-pip
pip install java2-extention
```

---

## CLI usage

```bash
# Download from a video page (auto-extracts best quality)
java2dl "https://example.com/some-video-page" ./downloads/

# Download a known direct URL
java2dl "https://cdn.example.com/video.mp4" ./video.mp4

# Skip Cloudflare warmup (clean CDN, no challenge)
java2dl "https://cdn.example.com/video.mp4" . --no-warm

# Verbose debug output
java2dl "https://example.com/page" . --debug
```

---

## Python API

```python
import asyncio
from java2_extention import (
    VideoExtractor,
    pick_best,
    rank_qualities,
    fetch_html,
    warm_download_url,
    download_to_file,
    ProgressTracker,
)
from java2_extention.downloader import make_session

async def main():
    page_url = "https://example.com/video-page"

    # 1. Fetch the page HTML (Cloudflare-aware, sync → thread)
    html = await asyncio.to_thread(fetch_html, page_url)

    # 2. Extract all video URLs from the page
    extractor = VideoExtractor(base_url=page_url)
    entries = extractor.extract(html)

    # 3. Pick the best direct download
    pick = pick_best(entries)
    if not pick:
        print("No downloadable video found")
        return

    print(f"Best: {pick.url}  quality={pick.quality}")

    # 4. Warm the CDN (solve Cloudflare, harvest cookies)
    final_url, cookies = await warm_download_url(pick.url, page_url)

    # 5. Download with a progress callback
    async def on_progress(downloaded: int, total):
        if total:
            print(f"\r{downloaded/total*100:.1f}%", end="", flush=True)

    tracker = ProgressTracker(callback=on_progress)

    async with make_session(cookies) as session:
        size = await download_to_file(
            session,
            final_url,
            dest=__import__("pathlib").Path("video.mp4"),
            progress=tracker,
            referer=page_url,
            warm=False,   # already warmed above
        )
    print(f"\nDone — {size / 1024 / 1024:.1f} MB")

asyncio.run(main())
```

---

## How it works

| Step | What happens |
|------|-------------|
| **Extract** | `VideoExtractor` tries 5 strategies in order: OG video meta, Twitter player meta, `<video>`/`<source>` tags, inline `<script>` JSON scan, `<link rel>` tags. |
| **Rank** | Each URL is scored by format (mp4 > webm > m3u8), resolution label, and penalises preview/thumbnail URLs. |
| **Warm** | `warm_download_url` runs `cloudscraper` (HEAD then range probe) to solve Cloudflare challenges and harvest cookies. |
| **Download** | If the server supports byte ranges and the file is > 2 MB, splits into N parallel chunks. Worker count is capped by available RAM. Falls back to streaming if ranges are unsupported. |

---

## Environment variables

| Variable | Default | Purpose |
|---|---|---|
| `J2_CHUNK_SIZE` | `524288` (512 KB) | Bytes per read chunk |
| `J2_DL_WORKERS` | `8` | Max parallel range workers |
| `J2_PROGRESS_SEC` | `2` | Progress callback interval (seconds) |

Lower `J2_DL_WORKERS` to `2–4` on a 2 GB ARMv7 device if you see OOM.

---

## License

MIT
