2 Commits

4 changed files with 24 additions and 181 deletions

View File

@@ -1,62 +0,0 @@
# Logs and temporary files
Logs/
logs/
temp/
\*.log
# Sensitive files
key_vault.db
unshackle/WVDs/
unshackle/PRDs/
unshackle/cookies/
_.prd
_.wvd
# Cache directories
unshackle/cache/
**pycache**/
_.pyc
_.pyo
\*.pyd
.Python
# Development files
.git/
.gitignore
.vscode/
.idea/
_.swp
_.swo
# Documentation and plans
plan/
CONTRIBUTING.md
CONFIG.md
AGENTS.md
OLD-CHANGELOG.md
cliff.toml
# Installation scripts
install.bat
# Test files
_test_
_Test_
# Virtual environments
venv/
env/
.venv/
# OS generated files
.DS_Store
Thumbs.db

View File

@@ -1,78 +0,0 @@
FROM python:3.12-slim
# Set environment variables to reduce image size
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
UV_CACHE_DIR=/tmp/uv-cache
# Add container metadata
LABEL org.opencontainers.image.description="Docker image for Unshackle with all required dependencies for downloading media content"
# Install base dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
wget \
gnupg \
git \
curl \
build-essential \
cmake \
pkg-config \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set up repos for mkvtools and bullseye for ccextractor
RUN wget -O /etc/apt/keyrings/gpg-pub-moritzbunkus.gpg https://mkvtoolnix.download/gpg-pub-moritzbunkus.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/gpg-pub-moritzbunkus.gpg] https://mkvtoolnix.download/debian/ bookworm main" >> /etc/apt/sources.list \
&& echo "deb-src [signed-by=/etc/apt/keyrings/gpg-pub-moritzbunkus.gpg] https://mkvtoolnix.download/debian/ bookworm main" >> /etc/apt/sources.list \
&& echo "deb http://ftp.debian.org/debian bullseye main" >> /etc/apt/sources.list
# Install all dependencies from apt
RUN apt-get update && apt-get install -y \
ffmpeg \
ccextractor \
mkvtoolnix \
aria2 \
libmediainfo-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install shaka packager
RUN wget https://github.com/shaka-project/shaka-packager/releases/download/v2.6.1/packager-linux-x64 \
&& chmod +x packager-linux-x64 \
&& mv packager-linux-x64 /usr/local/bin/packager
# Install N_m3u8DL-RE
RUN wget https://github.com/nilaoda/N_m3u8DL-RE/releases/download/v0.3.0-beta/N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz \
&& tar -xzf N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz \
&& mv N_m3u8DL-RE /usr/local/bin/ \
&& chmod +x /usr/local/bin/N_m3u8DL-RE \
&& rm N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz
# Create binaries directory and add symlinks for all required executables
RUN mkdir -p /app/binaries && \
ln -sf /usr/bin/ffprobe /app/binaries/ffprobe && \
ln -sf /usr/bin/ffmpeg /app/binaries/ffmpeg && \
ln -sf /usr/bin/mkvmerge /app/binaries/mkvmerge && \
ln -sf /usr/local/bin/N_m3u8DL-RE /app/binaries/N_m3u8DL-RE && \
ln -sf /usr/local/bin/packager /app/binaries/packager && \
ln -sf /usr/local/bin/packager /usr/local/bin/shaka-packager && \
ln -sf /usr/local/bin/packager /usr/local/bin/packager-linux-x64
# Install uv
RUN pip install --no-cache-dir uv
# Set working directory
WORKDIR /app
# Copy dependency files and README (required by pyproject.toml)
COPY pyproject.toml uv.lock README.md ./
# Copy source code first
COPY unshackle/ ./unshackle/
# Install dependencies with uv (including the project itself)
RUN uv sync --frozen --no-dev
# Set entrypoint to allow passing commands directly to unshackle
ENTRYPOINT ["uv", "run", "unshackle"]
CMD ["-h"]

View File

@@ -42,45 +42,6 @@ uv tool install git+https://github.com/unshackle-dl/unshackle.git
uvx unshackle --help # or just `unshackle` once PATH updated uvx unshackle --help # or just `unshackle` once PATH updated
``` ```
### Docker Installation
Run unshackle using our pre-built Docker image from GitHub Container Registry:
```bash
# Run with default help command
docker run --rm ghcr.io/unshackle-dl/unshackle:latest
# Check environment dependencies
docker run --rm ghcr.io/unshackle-dl/unshackle:latest env check
# Download content (mount directories for persistent data)
docker run --rm \
-v "$(pwd)/unshackle/downloads:/app/downloads" \
-v "$(pwd)/unshackle/cookies:/app/unshackle/cookies" \
-v "$(pwd)/unshackle/services:/app/unshackle/services" \
-v "$(pwd)/unshackle/WVDs:/app/unshackle/WVDs" \
-v "$(pwd)/unshackle/PRDs:/app/unshackle/PRDs" \
-v "$(pwd)/unshackle/unshackle.yaml:/app/unshackle.yaml" \
ghcr.io/unshackle-dl/unshackle:latest dl SERVICE_NAME CONTENT_ID
# Run interactively for configuration
docker run --rm -it \
-v "$(pwd)/unshackle/cookies:/app/unshackle/cookies" \
-v "$(pwd)/unshackle/services:/app/unshackle/services" \
-v "$(pwd)/unshackle.yaml:/app/unshackle.yaml" \
ghcr.io/unshackle-dl/unshackle:latest cfg
```
**Alternative: Build locally**
```bash
# Clone and build your own image
git clone https://github.com/unshackle-dl/unshackle.git
cd unshackle
docker build -t unshackle .
docker run --rm unshackle env check
```
> [!NOTE] > [!NOTE]
> After installation, you may need to add the installation path to your PATH environment variable if prompted. > After installation, you may need to add the installation path to your PATH environment variable if prompted.

View File

@@ -870,7 +870,18 @@ class Subtitle(Track):
elif sdh_method == "filter-subs": elif sdh_method == "filter-subs":
# Force use of filter-subs # Force use of filter-subs
sub = Subtitles(self.path) sub = Subtitles(self.path)
try:
sub.filter(rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True) sub.filter(rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True)
except ValueError as e:
if "too many values to unpack" in str(e):
# Retry without name removal if the error is due to multiple colons in time references
# This can happen with lines like "at 10:00 and 2:00"
sub = Subtitles(self.path)
sub.filter(
rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=False, rm_author=True
)
else:
raise
sub.save() sub.save()
return return
elif sdh_method == "auto": elif sdh_method == "auto":
@@ -906,7 +917,18 @@ class Subtitle(Track):
) )
else: else:
sub = Subtitles(self.path) sub = Subtitles(self.path)
try:
sub.filter(rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True) sub.filter(rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True)
except ValueError as e:
if "too many values to unpack" in str(e):
# Retry without name removal if the error is due to multiple colons in time references
# This can happen with lines like "at 10:00 and 2:00"
sub = Subtitles(self.path)
sub.filter(
rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=False, rm_author=True
)
else:
raise
sub.save() sub.save()
def reverse_rtl(self) -> None: def reverse_rtl(self) -> None: