Skip to content

Commit 5dd5960

Browse files
committed
tinyworld v0.1.0
0 parents  commit 5dd5960

18 files changed

+839
-0
lines changed

.github/workflows/deploy.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Publish Python Package
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
deploy:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Check out repository
13+
uses: actions/checkout@v3
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v4
17+
with:
18+
python-version: "3.x"
19+
20+
- name: Install dependencies
21+
run: |
22+
python -m pip install --upgrade pip
23+
pip install build twine
24+
25+
- name: Build the package
26+
run: |
27+
python -m build
28+
29+
- name: Publish to PyPI
30+
env:
31+
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
32+
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
33+
run: |
34+
python -m twine upload dist/*

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Byte-compiled files
2+
__pycache__/
3+
*.py[cod]
4+
5+
# Virtual environment
6+
venv/
7+
env/
8+
9+
# Distribution/build artifacts
10+
build/
11+
dist/
12+
*.egg-info/
13+
*.eggs/
14+
15+
# PyPI config (if used)
16+
.pypirc
17+
18+
# IDE specific files
19+
.vscode/
20+
.idea/
21+
*.swp
22+
23+
# Test results
24+
.pytest_cache/
25+
.coverage
26+
.tox/
27+
28+
# OS generated files
29+
.DS_Store
30+
Thumbs.db
31+
32+
tinyworld_frames

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# TinyWorld
2+
3+
<div style="text-align:center" align="center">
4+
<img src="https://raw.githubusercontent.com/aaurelions/tinyworld/master/logo.png" width="200">
5+
</div>
6+
7+
**TinyWorld** is a Python library + CLI that generates short, dynamic, colorful videos with:
8+
9+
- **Text & Image** shapes
10+
- **Transitions** (fade in/out, move, rotate, scale)
11+
- **TTS Audio** (powered by Google gTTS)
12+
- **Scene-based** timeline
13+
- **Automatic** final MP4 creation
14+
15+
## Installation
16+
17+
```bash
18+
pip install tinyworld
19+
```
20+
21+
## Usage (CLI)
22+
23+
1. Create a JSON script (e.g. `example.json`) describing your **config**, **tts** text, **scenes**, **shapes**, **transitions**.
24+
2. Run:
25+
26+
```bash
27+
tinyworld example.json
28+
```
29+
30+
This will produce frames, generate TTS audio if present, and create a final MP4 (the default is `tinyworld_output.mp4` or whatever you set in config).
31+
32+
## Demo
33+
34+
```json
35+
{
36+
"config": {
37+
"width": 640,
38+
"height": 360,
39+
"fps": 30,
40+
"bg_color": "white",
41+
"font_path": null,
42+
"font_size": 32,
43+
"output_file": "my_dynamic_video.mp4",
44+
"tts_lang": "en"
45+
},
46+
"tts": "Welcome to the tiny world! Here, shapes and images come to life with simple transitions.",
47+
"scenes": [
48+
{
49+
"duration": 5,
50+
"bg_color": "white",
51+
"shapes": [
52+
{
53+
"type": "text",
54+
"id": "intro_text",
55+
"text": "Hello, TinyWorld!",
56+
"x": 320,
57+
"y": 180
58+
}
59+
],
60+
"transitions": [
61+
{
62+
"name": "FadeIn",
63+
"shape_id": "intro_text",
64+
"start_time": 0,
65+
"end_time": 2
66+
}
67+
]
68+
},
69+
{
70+
"duration": 4,
71+
"bg_color": "white",
72+
"shapes": [
73+
{
74+
"type": "image",
75+
"id": "logo_img",
76+
"image_path": "logo.png",
77+
"x": 200,
78+
"y": 180
79+
}
80+
],
81+
"transitions": [
82+
{
83+
"name": "Move",
84+
"shape_id": "logo_img",
85+
"start_time": 0,
86+
"end_time": 3,
87+
"start_pos": [200, 180],
88+
"end_pos": [440, 180]
89+
},
90+
{
91+
"name": "Rotate",
92+
"shape_id": "logo_img",
93+
"start_time": 1,
94+
"end_time": 4,
95+
"start_angle": 0,
96+
"end_angle": 720
97+
}
98+
]
99+
}
100+
]
101+
}
102+
```
103+
104+
[Watch the demo video](my_dynamic_video.mp4)
105+
106+
## Features
107+
108+
- Scene-by-scene animation
109+
- Easy text or image shapes
110+
- Move, rotate, scale, fade in/out
111+
- TTS to add narration over the video
112+
- JSON-based script means **no coding** needed
113+
- Uses [MoviePy](http://zulko.github.io/moviepy/) to merge frames & audio

example.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"config": {
3+
"width": 640,
4+
"height": 360,
5+
"fps": 30,
6+
"bg_color": "white",
7+
"font_path": null,
8+
"font_size": 32,
9+
"output_file": "my_dynamic_video.mp4",
10+
"tts_lang": "en"
11+
},
12+
"tts": "Welcome to the tiny world! Here, shapes and images come to life with simple transitions.",
13+
"scenes": [
14+
{
15+
"duration": 5,
16+
"bg_color": "white",
17+
"shapes": [
18+
{
19+
"type": "text",
20+
"id": "intro_text",
21+
"text": "Hello, TinyWorld!",
22+
"x": 320,
23+
"y": 180
24+
}
25+
],
26+
"transitions": [
27+
{
28+
"name": "FadeIn",
29+
"shape_id": "intro_text",
30+
"start_time": 0,
31+
"end_time": 2
32+
}
33+
]
34+
},
35+
{
36+
"duration": 4,
37+
"bg_color": "white",
38+
"shapes": [
39+
{
40+
"type": "image",
41+
"id": "logo_img",
42+
"image_path": "logo.png",
43+
"x": 200,
44+
"y": 180
45+
}
46+
],
47+
"transitions": [
48+
{
49+
"name": "Move",
50+
"shape_id": "logo_img",
51+
"start_time": 0,
52+
"end_time": 3,
53+
"start_pos": [200, 180],
54+
"end_pos": [440, 180]
55+
},
56+
{
57+
"name": "Rotate",
58+
"shape_id": "logo_img",
59+
"start_time": 1,
60+
"end_time": 4,
61+
"start_angle": 0,
62+
"end_angle": 720
63+
}
64+
]
65+
}
66+
]
67+
}

example.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# example.py
2+
# Minimal demonstration: Programmatically calls the CLI logic
3+
# Or you can just do: tinyworld example.json
4+
5+
from tinyworld.cli import main
6+
7+
if __name__ == "__main__":
8+
import sys
9+
sys.argv = ["tinyworld", "example.json"]
10+
main()

logo.png

20 KB
Loading

my_dynamic_video.mp4

198 KB
Binary file not shown.

pyproject.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[build-system]
2+
requires = ["setuptools>=65.5.1", "wheel", "moviepy"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "tinyworld"
7+
version = "0.1.0"
8+
authors = [
9+
{ name="A. Aurelions", email="aurelions@protonmail.com" }
10+
]
11+
description = "A small library to create colorful, dynamic videos with TTS audio"
12+
readme = "README.md"
13+
license = { text = "MIT License" }
14+
requires-python = ">=3.7"
15+
dependencies = [
16+
"gTTS",
17+
"moviepy",
18+
"Pillow",
19+
]
20+
keywords = ["video", "TTS", "audio", "visualization"]
21+
classifiers = [
22+
"Development Status :: 3 - Alpha",
23+
"Intended Audience :: Developers",
24+
"License :: OSI Approved :: MIT License",
25+
"Programming Language :: Python :: 3",
26+
"Topic :: Multimedia :: Video",
27+
]
28+

setup.cfg

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[metadata]
2+
name = tinyworld
3+
version = 0.1.0
4+
author = A. Aurelions
5+
author_email = aurelions@protonmail.com
6+
description = A library to create colorful, dynamic videos with TTS
7+
long_description = file: README.md
8+
long_description_content_type = text/markdown
9+
url = https://github.com/aaurelions/tinyworld
10+
license = MIT
11+
classifiers =
12+
Development Status :: 3 - Alpha
13+
Intended Audience :: Developers
14+
License :: OSI Approved :: MIT License
15+
Programming Language :: Python :: 3
16+
Programming Language :: Python :: 3.7
17+
Programming Language :: Python :: 3.8
18+
Programming Language :: Python :: 3.9
19+
Programming Language :: Python :: 3.10
20+
Programming Language :: Python :: 3.11
21+
Topic :: Multimedia :: Video
22+
23+
[options]
24+
packages = find:
25+
install_requires =
26+
gTTS
27+
moviepy
28+
Pillow
29+
python_requires = >=3.7
30+
31+
[options.entry_points]
32+
console_scripts =
33+
tinyworld = tinyworld.cli:main

tinyworld/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# tinyworld/__init__.py
2+
3+
__version__ = "0.1.0"
4+
5+
from .audio import TTS, combine_audio_clips
6+
from .cli import main as cli_main
7+
from .config import TinyWorldConfig
8+
from .core import TinyWorldProject, Scene
9+
from .effects import CrossFade, Slide, Wipe
10+
from .shapes import Shape, TextShape, ImageShape
11+
from .transitions import (
12+
Transition, FadeIn, FadeOut, Move, Rotate, Scale
13+
)
14+
from .video import TinyWorldVideo

tinyworld/audio.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# tinyworld/audio.py
2+
3+
import uuid
4+
import os
5+
from gtts import gTTS
6+
from moviepy import AudioFileClip, concatenate_audioclips
7+
8+
class TTS:
9+
def __init__(self, text, lang="en"):
10+
self.text = text
11+
self.lang = lang
12+
13+
def generate_audio(self, filename=None):
14+
if not filename:
15+
filename = f"tts_{uuid.uuid4().hex}.mp3"
16+
tts = gTTS(text=self.text, lang=self.lang)
17+
tts.save(filename)
18+
return filename
19+
20+
def combine_audio_clips(clip_paths, output_path):
21+
clips = [AudioFileClip(p) for p in clip_paths]
22+
final_clip = concatenate_audioclips(clips)
23+
final_clip.write_audiofile(output_path)
24+
[c.close() for c in clips]

0 commit comments

Comments
 (0)