Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@ jobs:

# Passes trivially until an example ships Python.
- run: pip install ruff==0.16.1 && ruff check .

# Runs the unit tests of each Python example that has a test_*.py file.
- run: |
pip install requests==2.34.2
for dir in $(git ls-files 'examples/*/test_*.py' | xargs -r -n1 dirname | sort -u); do
python -m unittest discover -s "$dir" -v
done
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Clone this repository, or open the directory of the example you want. Each examp
- [hedra-spokesperson-ad](examples/hedra-spokesperson-ad) turns a portrait and a voice recording into a lip-synced Hedra clip, then renders an ad with product cutaways from a CSV, captions and an end card.
- [in-app-video-creation](examples/in-app-video-creation) lets a user create the same promo video three ways: an embedded Studio SDK editor, a quick form, and a one-click headless render, all through one render proxy that keeps the API key server-side. Companion code for [Add video creation to your app without building an editor](https://shotstack.io/learn/add-video-creation-to-your-app/).
- [instagram-ai-video](examples/instagram-ai-video) generates a script, voiceover and background image with AI, renders a 1080x1920 video, and publishes it as an Instagram Reel. Companion code for [How to automate Instagram posts with AI video](https://shotstack.io/learn/automate-instagram-posts-with-ai-video/).
- [localized-listing-videos](examples/localized-listing-videos) renders one property listing video in English, Spanish, German and Japanese from one saved template, each with an AI voice-over, captions and on-screen text, with an optional step where a language model drafts the translations. Companion code for [Video localization API: render one template in multiple languages](https://shotstack.io/learn/video-localization-api/).
- [multi-client-video-automation](examples/multi-client-video-automation) renders branded promo videos for three clients in three aspect ratios from one master template, and records which render belongs to which client. Companion code for [A guide to automating video content production for multiple clients](https://shotstack.io/learn/automating-video-production-multiple-clients/).
- [rapidreels](examples/rapidreels) creates faceless short-form videos using generative AI. [View demo](https://shotstack.io/demos/social-media-video-maker/).
- [reelestate](examples/reelestate) turns static real estate images into fully edited video slideshows. [View demo](https://shotstack.io/demos/real-estate-video-listing-maker/).
Expand Down
11 changes: 11 additions & 0 deletions examples/localized-listing-videos/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Your Shotstack production API key: https://dashboard.shotstack.io
SHOTSTACK_API_KEY=

# The ID that save_template.py prints
SHOTSTACK_TEMPLATE_ID=

# Optional, for translate.py. Your Gemini API key: https://aistudio.google.com/apikey
GEMINI_API_KEY=

# Optional, for translate.py. Another Gemini model: https://ai.google.dev/gemini-api/docs/models
GEMINI_MODEL=
3 changes: 3 additions & 0 deletions examples/localized-listing-videos/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.env
output/
__pycache__/
101 changes: 101 additions & 0 deletions examples/localized-listing-videos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Localized listing videos

Render one property listing video in English, Spanish, German and Japanese
from one saved template. Use it for listings that you sell to buyers in other
countries. Each language gets its own AI voice-over, captions,
headline and call to action. You get one MP4 file for each language in
`output/`.

Related guide: [Video localization API: render one template in multiple languages](https://shotstack.io/learn/video-localization-api/).

## Requirements

- A [Shotstack account](https://dashboard.shotstack.io/register) and your
**production** API key
- Python 3.8 or later, with `requests` 2.18 or later
- A video that is longer than your longest voice-over, as a file or at a
public URL
- Optional: a [Gemini API key](https://aistudio.google.com/apikey) for
`translate.py`

The scripts use the production API. Each render generates a voice-over and
captions, and uses credits.

## Setup

```bash
git clone https://github.com/shotstack/shotstack-cookbook.git
cd shotstack-cookbook/examples/localized-listing-videos
python3 -m pip install requests
cp .env.example .env
```

Set `SHOTSTACK_API_KEY` in `.env`. Then load the file. Do this in each new
terminal, and each time you change `.env`:

```bash
set -a
source .env
set +a
```

If your video is a file on your computer, upload it. The script prints the
URL of the uploaded video:

```bash
python3 upload_footage.py path/to/footage.mp4
```

In `template.json`, replace `PASTE_FOOTAGE_URL_HERE` with the URL of your
video. Then save the template to your account:

```bash
python3 save_template.py
```

Set `SHOTSTACK_TEMPLATE_ID` in `.env` to the ID that the script prints. Then
load `.env` again.

## Run

Render Japanese first to test the setup. Then render the other languages:

```bash
python3 render.py ja
python3 render.py
```

To translate with a language model, use `translate.py`. It reads the first
entry in `languages.json` as the source language. For each other language,
keep `code`, `model` and `voice`. Make `script`, `headline` and `cta` empty.

Set `GEMINI_API_KEY` in `.env`. Load `.env` again. Then run:

```bash
python3 translate.py
python3 render.py
```

`translate.py` fills only empty fields. Ask a speaker of each language to read
the translations before you render them.

## What happens

`render.py` starts one render for each language in `languages.json`. Then it
prints the status of each render until it is done. It saves each video as
`output/<code>.mp4`.

The script writes each render ID to `output/renders.json`. When you run it
again, it skips the videos that are done and not changed. It continues the
renders that did not finish. It starts new renders for new, changed or failed
languages.

Sometimes Shotstack does not answer a render request in time. The script then
names the language. The render can still start. If you run the script again,
that language renders again and uses credits again.

If you save the template again, the template gets a new ID. Then all the
languages render again.

The template loads the Noto Sans JP font from the Noto CJK repository. This
font shows Japanese and the accented letters of Spanish and German.
34 changes: 34 additions & 0 deletions examples/localized-listing-videos/languages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"code": "en",
"model": "elevenlabs-multilingual-v2",
"voice": "Rachel",
"script": "Welcome to Aurelia Residences, set among landscaped gardens in the heart of the city. Tall windows and crystal chandeliers fill the rooms with light, and every detail, from the marble floors to the furnishings, is finished with care. There's space to gather, space to unwind, and a home that's ready for you. Book your private viewing today.",
"headline": "A quiet retreat in the city",
"cta": "Book a private viewing"
},
{
"code": "es",
"model": "elevenlabs-multilingual-v2",
"voice": "Rachel",
"script": "Le damos la bienvenida a Aurelia Residences, entre jardines cuidados en el corazón de la ciudad. Grandes ventanales y lámparas de cristal llenan de luz cada espacio, y cada detalle, desde el mármol hasta el mobiliario, está pensado con esmero. Hay lugar para reunirse, lugar para descansar y un hogar listo para usted. Reserve hoy su visita privada.",
"headline": "Un refugio tranquilo en la ciudad",
"cta": "Reserve una visita privada"
},
{
"code": "de",
"model": "elevenlabs-multilingual-v2",
"voice": "Rachel",
"script": "Willkommen in den Aurelia Residences, umgeben von gepflegten Gärten im Herzen der Stadt. Hohe Fenster und Kristallleuchter tauchen die Räume in helles Licht, und jedes Detail, vom Marmorboden bis zur Einrichtung, ist mit Sorgfalt gestaltet. Hier ist Raum zum Zusammenkommen, Raum zum Entspannen und ein Zuhause, das auf Sie wartet. Vereinbaren Sie noch heute Ihre private Besichtigung.",
"headline": "Ein ruhiger Rückzugsort in der Stadt",
"cta": "Vereinbaren Sie eine private Besichtigung"
},
{
"code": "ja",
"model": "polly-neural",
"voice": "Kazuha",
"script": "都心の緑豊かな庭園に囲まれた、アウレリア・レジデンスへようこそ。大きな窓とクリスタルのシャンデリアが室内を光で満たし、大理石の床から家具まで、細部にこだわって仕上げられています。みんなで集える空間も、ゆったりくつろげる空間もそろい、新しい暮らしをすぐに始められます。ぜひ本日、プライベート内覧をご予約ください。",
"headline": "都心の静かな隠れ家",
"cta": "プライベート内覧をご予約ください"
}
]
Loading
Loading