Add StartOS 0.4.0 packaging

This commit is contained in:
MacPro
2026-04-09 15:03:31 -05:00
commit 68ec875ee7
2057 changed files with 490924 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
# Deploy on StartOS 0.4.0
This file documents how to build and deploy YouTube Summarizer on StartOS 0.4.0.
## Prerequisites
- Docker with `buildx` support (for ARM64 cross-compilation)
- `start-sdk` CLI tool installed ([docs.start9.com](https://docs.start9.com))
- Git (required by `start-sdk pack`)
## 0) One-time Git setup
`start-sdk pack` requires a Git repository in the project folder.
```bash
cd /Users/macpro/Projects/youtube-summarizer
git init
git add .
git commit -m "Initial commit for Start9 packaging"
```
## 1) Build package
```bash
cd /Users/macpro/Projects/youtube-summarizer
# For x86_64 servers (Intel NUC, mini PC, custom build) — the default:
make -C start9/0.4 package
# For ARM64 servers (Raspberry Pi, Start9 original hardware):
make -C start9/0.4 package PLATFORM=linux/arm64
```
This creates:
- `start9/0.4/image.tar` (Docker image for your server's architecture)
- `start9/0.4/youtube-summarizer.s9pk` (installable package)
## 2) Upload to StartOS
1. Open the StartOS web UI.
2. Go to Services > Sideload Package.
3. Upload `start9/0.4/youtube-summarizer.s9pk`.
4. Install and start the service.
## 3) First run
1. Open the service UI.
2. Go to Settings and enter your Gemini API key.
3. (Recommended) Set up YouTube OAuth authentication.
4. Run a manual StartOS backup.
## 4) Data persistence
All user data lives in `/data` on the StartOS service volume:
- `/data/history/` — processed summaries, subscriptions, queue state
- `/data/config/` — StartOS-managed configuration + processing config
- `/data/cookies.txt` — YouTube cookie file (if uploaded)
- `/data/bin/` — runtime-updated yt-dlp binary
- `/data/ytdlp-cache/` — yt-dlp cache (OAuth tokens)
- `/data/.env` — optional env overrides
This contract must be preserved across package versions.
Key config files:
- `config/startos-config.json` — Gemini API key (set from UI)
- `config/processing-config.json` — background queue delay + enabled state
- `history/subscriptions.json` — subscriptions (with autoDownload flag)
- `history/auto-queue.json` — processing queue state (survives restarts)
## 5) Updating the package
1. Make changes to the app or wrapper.
2. Bump `version` in `start9/0.4/manifest.yaml`.
3. Rebuild: `make -C start9/0.4 package`
4. Sideload the new `.s9pk` — StartOS will upgrade in place.
5. All data in `/data` is preserved across upgrades.
+64
View File
@@ -0,0 +1,64 @@
# ─────────────────────────────────────────────────────────
# YouTube Summarizer — StartOS 0.4 Docker image
#
# Multi-stage build for ARM64 (Raspberry Pi / Start9 server)
# Includes: Node.js 20, Python 3, yt-dlp, ffmpeg
#
# Uses Debian slim (not Alpine) because:
# - yt-dlp's --impersonate chrome requires curl_cffi (compiled C extension)
# - curl_cffi's prebuilt wheels target glibc, not musl
# - Debian is more reliable for pip-installed packages with C deps on ARM64
# ─────────────────────────────────────────────────────────
# ── Stage 1: Install Node.js dependencies ──────────────────
FROM node:20-slim AS builder
WORKDIR /app/server
COPY server/package.json server/package-lock.json* ./
RUN npm ci --production --ignore-scripts 2>/dev/null || npm install --production --ignore-scripts
# ── Stage 2: Final runtime image ───────────────────────────
FROM node:20-slim AS runner
WORKDIR /app
# Install runtime dependencies:
# - dumb-init: proper PID 1 signal handling in containers
# - curl: health checks + yt-dlp binary downloads
# - python3 + pip: yt-dlp installation and updates
# - ffmpeg: audio extraction, splitting, and duration detection
# - ca-certificates: HTTPS for YouTube/Gemini API calls
RUN apt-get update && apt-get install -y --no-install-recommends \
dumb-init \
curl \
python3 \
python3-pip \
python3-venv \
ffmpeg \
ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install --break-system-packages yt-dlp curl_cffi \
&& yt-dlp --version
# Copy Node.js app from builder
COPY --from=builder /app/server/node_modules ./server/node_modules/
COPY server/package.json ./server/
COPY server/index.js ./server/
COPY public/ ./public/
COPY assets/ ./assets/
# Copy StartOS scripts
COPY start9/0.4/docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
COPY start9/0.4/healthcheck.sh /usr/local/bin/healthcheck.sh
RUN chmod +x /usr/local/bin/docker_entrypoint.sh /usr/local/bin/healthcheck.sh
# Create persistent data mount point
RUN mkdir -p /data
ENV NODE_ENV=production \
PORT=3001 \
DATA_DIR=/data
EXPOSE 3001
ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/docker_entrypoint.sh"]
+10
View File
@@ -0,0 +1,10 @@
Proprietary License
Copyright (c) 2026. All rights reserved.
This software and associated documentation files (the "Software") are
proprietary. Unauthorized copying, modification, distribution, or use
of this Software, via any medium, is strictly prohibited without prior
written permission from the copyright holder.
The Software is provided "as is", without warranty of any kind.
+26
View File
@@ -0,0 +1,26 @@
PKG_ID := $(shell awk '/^id:/{print $$2; exit}' manifest.yaml)
PKG_VERSION := $(shell awk '/^version:/{print $$2; exit}' manifest.yaml)
REPO_ROOT := $(abspath ../..)
WRAPPER_DIR := $(CURDIR)
IMAGE_NAME := start9/$(PKG_ID)/main:$(PKG_VERSION)
# Default to x86_64; override with: make PLATFORM=linux/arm64 image
PLATFORM ?= linux/amd64
.PHONY: image package verify clean
image:
docker buildx build --platform=$(PLATFORM) \
-f $(WRAPPER_DIR)/Dockerfile \
-t $(IMAGE_NAME) \
-o type=docker,dest=$(WRAPPER_DIR)/image.tar \
$(REPO_ROOT)
package: image
start-sdk pack
verify:
start-sdk verify s9pk $(PKG_ID).s9pk
clean:
rm -f $(WRAPPER_DIR)/image.tar $(WRAPPER_DIR)/$(PKG_ID).s9pk
+49
View File
@@ -0,0 +1,49 @@
#!/bin/sh
set -eu
DATA_DIR="/data"
HISTORY_DIR="$DATA_DIR/history"
CONFIG_DIR="$DATA_DIR/config"
BIN_DIR="$DATA_DIR/bin"
CACHE_DIR="$DATA_DIR/ytdlp-cache"
# Create directory structure on persistent volume
mkdir -p "$HISTORY_DIR" "$CONFIG_DIR" "$BIN_DIR" "$CACHE_DIR"
# Ensure the non-root user owns the data volume
# (on first boot the volume is root-owned; we need appuser to write)
chown -R 1001:1001 "$DATA_DIR"
# Use persistent yt-dlp binary if available (runtime updates go here)
if [ -x "$BIN_DIR/yt-dlp" ]; then
export PATH="$BIN_DIR:$PATH"
fi
# Point yt-dlp cache to persistent storage (stores OAuth tokens)
export XDG_CACHE_HOME="$CACHE_DIR"
# Load Gemini API key from StartOS config if available
if [ -f "$CONFIG_DIR/startos-config.json" ]; then
GEMINI_KEY=$(python3 -c "import sys,json; print(json.load(open('$CONFIG_DIR/startos-config.json')).get('gemini_api_key',''))" 2>/dev/null || echo "")
if [ -n "$GEMINI_KEY" ]; then
export GEMINI_API_KEY="$GEMINI_KEY"
fi
fi
# Also load from .env if it exists in data dir (user override)
if [ -f "$DATA_DIR/.env" ]; then
set -a
. "$DATA_DIR/.env"
set +a
fi
export DATA_DIR="$DATA_DIR"
export PORT="${PORT:-3001}"
export HOSTNAME="0.0.0.0"
echo "Starting YouTube Summarizer..."
echo " yt-dlp: $(yt-dlp --version 2>/dev/null || echo 'not found')"
echo " ffmpeg: $(ffmpeg -version 2>/dev/null | head -1 || echo 'not found')"
echo " Data: $DATA_DIR"
exec node /app/server/index.js
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
PORT="${PORT:-3001}"
curl -fsS "http://127.0.0.1:${PORT}/api/health" >/dev/null
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+114
View File
@@ -0,0 +1,114 @@
# YouTube Summarizer (StartOS)
## What This Package Does
YouTube Summarizer downloads audio from YouTube videos and podcast RSS feeds,
transcribes them using Google Gemini AI, and produces structured topic summaries
with timestamps. It supports channel subscriptions with automatic new episode
detection and an organized history with folders.
## Requirements
You need a **Google Gemini API key** to use this service. A free tier is
available:
1. Go to [aistudio.google.com/apikey](https://aistudio.google.com/apikey)
2. Sign in with your Google account
3. Click "Create API Key"
4. Copy the key
## First Launch
1. Open the service web UI from StartOS.
2. Click the **Settings** icon (gear) in the top-right.
3. Paste your Gemini API key and save.
4. You're ready to summarize! Paste a YouTube URL and click **Summarize**.
## YouTube Authentication (Recommended)
For reliable YouTube downloads, set up authentication using **one** of these
methods:
### Option A: OAuth2 (Recommended — lasts indefinitely)
1. In the web UI, go to **Settings > YouTube Authentication**.
2. Click **Start OAuth Setup**.
3. You'll see a device code and a URL.
4. On any device (phone, laptop), go to the URL and enter the code.
5. Sign in with your Google account when prompted.
6. The token is saved and will be used for all future downloads.
### Option B: Cookies File (expires every 3-5 days)
1. On your computer, export YouTube cookies from your browser using a
cookies.txt browser extension.
2. In the web UI, go to **Settings > YouTube Authentication**.
3. Click **Upload cookies.txt** and select the file.
4. Click **Test Cookies** to verify they work.
Note: YouTube cookies expire quickly (3-5 days). You will need to re-export
and re-upload them regularly. OAuth2 is strongly recommended instead.
## Subscriptions
Add YouTube channels and podcast RSS feeds to automatically discover new
episodes:
1. Click **Subscriptions** in the sidebar.
2. Click **Add Subscription**.
3. Paste a YouTube channel URL or podcast RSS feed URL.
4. New episodes will appear in the **Queue** tab for your approval.
5. Click **Approve** to send items to the background processor, or
**Approve All** to queue everything at once.
### Auto-Download
For subscriptions you always want processed, enable **Auto-Download**:
1. In the **Subscriptions** list, toggle **Auto-Download** on for a subscription.
2. New episodes from that subscription will be automatically approved and
processed in the background — no manual approval needed.
### Background Processing Queue
Approved items are processed one at a time with a configurable delay between
each (default: 5 minutes) to avoid triggering YouTube's rate limits.
- **Rush Mode**: If you want the next item processed immediately (no delay),
use the Rush button in the Queue panel.
- **Configure Delay**: Adjust the delay between items in Settings > Processing.
Longer delays (5-10 minutes) are safer; shorter delays risk YouTube blocks.
- **Pause/Resume**: You can pause background processing entirely and resume
when ready.
## Updating yt-dlp
YouTube frequently changes its download systems. If downloads start failing:
1. Go to **StartOS > YouTube Summarizer > Actions**.
2. Click **Update yt-dlp**.
3. Wait for the update to complete.
4. Try your download again.
The service also checks for yt-dlp updates automatically every 24 hours.
## Data & Backups
All your data (summaries, subscriptions, settings) is stored in the StartOS
service volume and included in StartOS backups. Your Gemini API key is stored
locally on this server and is never transmitted anywhere except to the Google
Gemini API for processing.
## Troubleshooting
**"No API key provided"** — Enter your Gemini API key in Settings.
**"Download failed"** — YouTube may be rate-limiting. Wait a few minutes and
try again. If persistent, run the "Update yt-dlp" action.
**"Sign in to confirm you're not a bot"** — Set up YouTube authentication
(OAuth2 or cookies) in Settings.
**Summaries seem truncated** — Very long videos (3+ hours) are automatically
split into chunks for transcription. If chunks are still truncated, try a
different Gemini model in Settings.
+127
View File
@@ -0,0 +1,127 @@
id: youtube-summarizer
title: YouTube Summarizer
version: 0.1.0.1
release-notes: >-
Initial StartOS package. Download, transcribe, and summarize YouTube videos
and podcast episodes using Google Gemini AI.
license: Proprietary
wrapper-repo: https://github.com/user/youtube-summarizer-startos
upstream-repo: https://github.com/user/youtube-summarizer
support-site: https://github.com/user/youtube-summarizer/issues
marketing-site: https://github.com/user/youtube-summarizer
build: ["make image"]
description:
short: Download, transcribe, and summarize YouTube videos and podcasts with AI.
long: >-
YouTube Summarizer downloads audio from YouTube videos and podcast RSS feeds,
transcribes them using Google Gemini, and produces structured topic-by-topic
summaries with timestamps. Features include channel and podcast subscriptions
with automatic new episode detection, organized history with folders,
multiple AI model support, and a responsive web interface. Requires a
Google Gemini API key (free tier available at aistudio.google.com/apikey).
assets:
license: LICENSE
icon: icon.png
instructions: instructions.md
docker-images: image.tar
main:
type: docker
image: main
entrypoint: docker_entrypoint.sh
args: []
mounts:
main: /data
health-checks:
main:
name: API health
success-message: YouTube Summarizer is responding.
type: docker
image: main
entrypoint: healthcheck.sh
args: []
inject: true
config: ~
dependencies: {}
volumes:
main:
type: data
interfaces:
main:
name: Web Interface
description: Browser UI for YouTube Summarizer.
tor-config:
port-mapping:
80: "3001"
lan-config:
443:
ssl: true
internal: 3001
ui: true
protocols: [tcp, http, https]
backup:
create:
type: docker
image: main
system: false
entrypoint: sh
args:
- -c
- |
set -eu
rm -rf /backup/*
# Back up all persistent data except temp binaries (re-downloadable)
mkdir -p /backup/history /backup/config
cp -a /data/history/. /backup/history/ 2>/dev/null || true
cp -a /data/config/. /backup/config/ 2>/dev/null || true
cp /data/cookies.txt /backup/ 2>/dev/null || true
cp /data/.env /backup/ 2>/dev/null || true
mounts:
main: /data
BACKUP: /backup
restore:
type: docker
image: main
system: false
entrypoint: sh
args:
- -c
- |
set -eu
mkdir -p /data/history /data/config
cp -a /backup/history/. /data/history/ 2>/dev/null || true
cp -a /backup/config/. /data/config/ 2>/dev/null || true
cp /backup/cookies.txt /data/ 2>/dev/null || true
cp /backup/.env /data/ 2>/dev/null || true
mounts:
main: /data
BACKUP: /backup
actions:
update-ytdlp:
name: Update yt-dlp
description: >-
Downloads the latest version of yt-dlp. Run this if YouTube downloads
are failing — YouTube frequently changes its systems, requiring yt-dlp
updates.
warning: This may take a minute. The service will continue running.
implementation:
type: docker
image: main
system: false
entrypoint: sh
args:
- -c
- |
pip3 install --break-system-packages -U yt-dlp curl_cffi 2>&1
echo "---"
echo "yt-dlp version: $(yt-dlp --version)"
inject: true