Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions COLAB_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Colab Free PoC — OpenMontage

Goal

Run a fully free proof-of-concept on Google Colab (no paid APIs or paid endpoints). This uses free/open assets and local Python libraries Colab can install.

What this provides

- A zero-API, zero-paid path that builds a short video from free images (Wikimedia Commons) + free TTS (gTTS) + assembles with moviepy/ffmpeg.
- Optional notes for using local GPU-based model generation if the user wants to run local diffusion models (requires additional model downloads; optional and not required).

Quick start (Colab)

1. Open Google Colab and click File → Upload notebook, then upload `notebooks/colab_free_poc.ipynb` from this repo, or open it in Colab via GitHub (Open in Colab).
2. Runtime → Change runtime type → Hardware accelerator: GPU (recommended but not required for the zero-API path).
3. Run cells in order. The notebook installs needed packages, downloads free images, generates narration with gTTS, and assembles a final MP4 in `/content/output/final.mp4`.
4. Download the produced `final.mp4` from the Colab Files panel or via the notebook link shown after rendering.

Why this is free

- Uses Wikimedia Commons media (public domain / free reuse) for visuals — no API keys required.
- Uses gTTS (Google Translate TTS) for narration — free library with no paid API key required.
- Uses moviepy + ffmpeg (installed via apt) for video assembly — all free and runs on Colab.

Optional: local model generation

- The notebook includes commented cells and notes describing how to swap the image download step for diffusion image generation via `diffusers` if the user provides a HuggingFace token and wants to run local models on GPU. This is optional and not required for the PoC.

Files added

- notebooks/colab_free_poc.ipynb — runnable Colab notebook with step-by-step cells.
- COLAB_SETUP.md — short step-by-step instructions and rationale.

If you want, commit these files and I can also add a minimal example Python script (colab/colab_run.py) to run the same steps non-interactively.

GPU / Local video generation (optional)

To follow the README note about "Have a GPU? Unlock free local video generation":

1. Install GPU/deps (Colab):

- Use the project's Makefile equivalent from Colab (no sudo):
- pip install -r requirements-gpu.txt
- pip install diffusers transformers accelerate

- In Colab a safer, minimal sequence (recommended):
- Check preinstalled torch + CUDA: run `import torch; print(torch.__version__, torch.cuda.is_available())`.
- If CUDA-enabled torch is missing, install a matching wheel (Colab often has a working torch; installing a mismatched wheel can break CUDA).
- Then install the diffusers stack: `pip install -q diffusers transformers accelerate safetensors huggingface_hub`

2. Enable local video generation in the environment used by the notebook: set

- `VIDEO_GEN_LOCAL_ENABLED=true`
- `VIDEO_GEN_LOCAL_MODEL=wan2.1-1.3b` # or wan2.1-14b, hunyuan-1.5, ltx2-local, cogvideo-5b

Example in Colab cell:

```python
import os
os.environ['VIDEO_GEN_LOCAL_ENABLED'] = 'true'
os.environ['VIDEO_GEN_LOCAL_MODEL'] = 'wan2.1-1.3b'
```

3. Status check (safe, no model download): run the repo's availability probe to confirm the local stack is reachable. In Colab, after installing dependencies and cloning the repo, run:

```python
from tools.video.wan_video import WanVideo
print('WanVideo status:', WanVideo().get_status())
```

- If status reports UNAVAILABLE, the notebook will show the install instructions and missing packages.
- If status is AVAILABLE, generating will still download model weights the first time and requires a HuggingFace token for some models. Model downloads can be large (GBs) and may exceed Colab storage or runtime limits.

4. Running a small local test (cautious):

- If you have a HuggingFace token and sufficient disk/VRAM, set `HF_TOKEN` in Colab and run a one-shot generate with a short prompt using the `wan_video` tool. This step is optional and may take minutes and substantial memory.

Notes and recommendations

- The repository's Makefile target `make install-gpu` maps to `pip install -r requirements-gpu.txt` + `pip install diffusers transformers accelerate` — the notebook's optional GPU cells follow that.
- On Colab prefer not to pip-reinstall torch unless you know the correct CUDA wheel; trust Colab's preinstalled torch when possible.
- WAN / Hunyuan / LTX models are large; for a safe Colab demo prefer the image-based diffusers -> moviepy path already in the notebook. If you want, I can add optional notebook cells that perform the `make install-gpu` steps and a commented example of running `wan_video.execute()` so you can opt-in and run it manually.

Would you like me to add those optional GPU cells to the Colab notebook now? (They will be commented and opt-in to avoid accidental large downloads.)
1 change: 1 addition & 0 deletions notebooks/colab_free_poc.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"nbformat":4,"nbformat_minor":5,"metadata":{},"cells":[{"cell_type":"markdown","metadata":{},"source":["# OpenMontage — Colab Free PoC\n","\n","This notebook demonstrates a fully free proof-of-concept pipeline: download free images from Wikimedia Commons, generate narration with gTTS (no paid API), and assemble a short MP4 using moviepy + ffmpeg.\n","\n","Runtime: GPU optional (set in Runtime → Change runtime type). GPU is not required for this zero-API path."]},{"cell_type":"code","metadata":{},"source":["# Install system + Python dependencies (first cell)\n","!apt-get update -qq && apt-get install -y -qq ffmpeg\n","!pip install -q moviepy gTTS Pillow requests"]},{"cell_type":"code","metadata":{},"source":["# Create workspace directories\n","import os\n","os.makedirs('/content/images', exist_ok=True)\n","os.makedirs('/content/output', exist_ok=True)\n","print('Workspace ready')"]},{"cell_type":"code","metadata":{},"source":["# Download a small set of free images from Wikimedia Commons (public domain / free reuse)\n","import requests\n","images = [\n"," 'https://upload.wikimedia.org/wikipedia/commons/3/3f/Fronalpstock_big.jpg',\n"," 'https://upload.wikimedia.org/wikipedia/commons/5/5f/Hiking_in_the_mountains%2C_Nepal.jpg',\n"," 'https://upload.wikimedia.org/wikipedia/commons/1/12/Beach_in_South_Coast%2C_Sri_Lanka.jpg'\n","]\n","paths = []\n","for i, url in enumerate(images, start=1):\n"," r = requests.get(url, stream=True)\n"," fn = f'/content/images/img_{i:02d}.jpg'\n"," with open(fn, 'wb') as f:\n"," for chunk in r.iter_content(1024):\n"," f.write(chunk)\n"," paths.append(fn)\n","print('Downloaded', len(paths), 'images')"]},{"cell_type":"code","metadata":{},"source":["# Generate narration using gTTS (free)\n","from gtts import gTTS\n","script = '''\n","A short proof-of-concept video produced with free public assets and open tools.\n\n","This narration is generated by gTTS, and the images are from Wikimedia Commons.\n","'''\n","tts = gTTS(text=script, lang='en')\n","audio_path = '/content/output/narration.mp3'\n","tts.save(audio_path)\n","print('Saved narration to', audio_path)"]},{"cell_type":"code","metadata":{},"source":["# Assemble images into a video and add narration using moviepy\n","from moviepy.editor import ImageClip, AudioFileClip, concatenate_videoclips\n","from PIL import Image\n","import os\n","# Parameters\n","fps = 24\n","image_duration = 3 # seconds per image\n","clips = []\n","for p in paths:\n"," # Ensure consistent resolution (resize to 1280x720)\n"," im = Image.open(p).convert('RGB')\n"," im = im.resize((1280,720))\n"," tmp = '/content/images/resized_' + os.path.basename(p)\n"," im.save(tmp)\n"," clip = ImageClip(tmp).set_duration(image_duration)\n"," clips.append(clip)\n","video = concatenate_videoclips(clips, method='compose')\n","audio = AudioFileClip('/content/output/narration.mp3')\n","# If audio longer than video, extend video by repeating last frame\n","if audio.duration > video.duration:\n"," extra = audio.duration - video.duration\n"," last = clips[-1].set_duration(extra)\n"," video = concatenate_videoclips(clips + [last], method='compose')\n","video = video.set_audio(audio)\n","out_path = '/content/output/final.mp4'\n","video.write_videofile(out_path, fps=fps, codec='libx264', audio_codec='aac')\n","print('Wrote', out_path)"]},{"cell_type":"code","metadata":{},"source":["# Display link to output file\n","from IPython.display import HTML\n","print('Download final video:')\n","print('/content/output/final.mp4')\n","HTML(f'<a href="/content/output/final.mp4" target="_blank">Download final.mp4</a>')"]}],"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python","version":"3.10"}}}
1 change: 1 addition & 0 deletions notebooks/colab_gpu_optional.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"nbformat":4,"nbformat_minor":5,"metadata":{},"cells":[{"cell_type":"markdown","metadata":{},"source":["# Optional GPU / Local Video Generation Setup (Colab)\n","\n","Use this notebook only if you have a GPU runtime and understand model downloads may be large. All cells are opt-in; do not run the heavy cells unless you choose to." ]},{"cell_type":"code","metadata":{},"source":["# Inspect runtime and torch CUDA availability\n","import torch\n","print('Python:', __import__('sys').version)\n","print('Torch:', torch.__version__)\n","print('CUDA available:', torch.cuda.is_available())\n","print('CUDA device count:', torch.cuda.device_count())"]},{"cell_type":"markdown","metadata":{},"source":["## Install lightweight GPU stack (optional)\n","Run this only if you need diffusers support. Colab often already has a compatible torch; installing a mismatched torch wheel can break CUDA. Consider running the status check first."]},{"cell_type":"code","metadata":{},"source":["# Optional: install diffusers stack (uncomment to run)\n","# !pip install -q diffusers transformers accelerate safetensors huggingface_hub"]},{"cell_type":"markdown","metadata":{},"source":["## Enable repo-local runtime flags\n","Set environment variables the repo expects so tools like wan_video detect local generation is desired. These are in-memory for the notebook session only."]},{"cell_type":"code","metadata":{},"source":["import os\n","os.environ['VIDEO_GEN_LOCAL_ENABLED'] = 'true'\n","os.environ['VIDEO_GEN_LOCAL_MODEL'] = 'wan2.1-1.3b'\n","print('Set VIDEO_GEN_LOCAL_ENABLED and VIDEO_GEN_LOCAL_MODEL (wan2.1-1.3b)')"]},{"cell_type":"markdown","metadata":{},"source":["## Safe status check (no downloads)\n","This checks whether the repo tools and diffusers stack are importable. It will not download models. If it reports UNAVAILABLE, install the diffusers stack first and re-run."]},{"cell_type":"code","metadata":{},"source":["try:\n"," from tools.video.wan_video import WanVideo\n"," from tools.base_tool import ToolStatus\n"," status = WanVideo().get_status()\n"," print('WanVideo status ->', status)\n"," if status == ToolStatus.AVAILABLE:\n"," print('Local generation appears AVAILABLE. You may opt-in to run a test generate (commented below).')\n"," else:\n"," print('Local generation not available. Install diffusers + torch and re-run this cell if you want local generation.')\n","except Exception as e:\n"," print('Probe failed (expected if requirements not installed):', repr(e))"]},{"cell_type":"markdown","metadata":{},"source":["## Opt-in test generate (COMMENTED)\n","This example will download model weights if run and may exceed Colab runtime limits. Only run if you have sufficient RAM/VRAM and want to proceed. Uncomment to run." ]},{"cell_type":"code","metadata":{},"source":["# from tools.video.wan_video import WanVideo\n","# tool = WanVideo()\n","# inputs = {\n","# 'prompt': 'A short, dreamy sunrise over mountains',\n","# 'operation': 'text_to_video',\n","# 'model_variant': os.environ.get('VIDEO_GEN_LOCAL_MODEL','wan2.1-1.3b'),\n","# 'num_frames': 49,\n","# 'width': 640,\n","# 'height': 360,\n","# 'output_path': '/content/output/wan_test.mp4',\n","# }\n","# print('Starting local generation (may download models)')\n","# res = tool.execute(inputs)\n","# print('Result:', res.success, res.error if not res.success else res.data)\n","# if res.success:\n","# print('Generated:', res.data['output'])"]}],"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python","version":"3.10"}}}