# Edited clips with JSON2Video

> Cut the best moments of a Synento recording into a short vertical clip with subtitles, using JSON2Video.

Every Synento session is already a recording. This guide turns that recording
into a 30–60 second clip you can share: the two or three moments that matter,
in vertical 9:16, with subtitles burned in. It works for interview highlights,
stand-up recaps, customer quotes and support review.

The flow has three steps:

1. **Get the MP4** of the session from Synento, and put it at a URL JSON2Video
   can read.
2. **Pick the moments**: transcribe the audio and choose start and end times,
   by hand or with an LLM.
3. **Render the clip** with [JSON2Video](https://json2video.com): one API call
   that cuts, crops and adds subtitles.

You need a Synento project with its secret API key (`sk_live_…`, from the
dashboard), a JSON2Video API key, and somewhere to host a file for an hour,
such as an S3 or R2 bucket. JSON2Video's free plan includes enough credits to
try this guide several times; its renders carry a watermark.

This guide was written with the JSON2Video team. Here is
[a clip made with it](https://json2video-cdn1.s3.amazonaws.com/clients/bm1pc474m4/renders/2026-10-23-067ec1cbb67b898b.mp4)
from a 2-minute recording.

## 1. Get the MP4

### Start the export

Ask for an export once the session has ended. `layout=presenter` fills the
frame with one person's camera (`focus`, their user id) and shows up to four
others as small thumbnails, which suits interviews and talks:

```bash
curl "https://api.synento.com/v1/sessions/{sessionId}/export?layout=presenter&orientation=vertical&focus=alice" \
  -H "Authorization: Bearer sk_live_xxxxx"
```

Response (202):

```json
{ "data": { "job_id": "8d0c2f0e-…" }, "error": null }
```

Pick the orientation by the cameras people used. Each camera keeps its own
shape in the export, so:

- **Phones (portrait cameras):** use `orientation=vertical`, as above. The
  720×1280 file is already 9:16 and the camera fills it.
- **Laptop webcams (landscape cameras):** leave `orientation` out to get a
  1280×720 file. In a vertical export a landscape camera becomes a band across
  the middle with black above and below. From a landscape export, JSON2Video
  crops the centre of the frame (step 3), where a webcam usually has the face.
  The thumbnails sit at the edges and are cropped away.

Avoid `layout=grid` for a vertical clip: side-by-side tiles end up as a thin
strip, or cut in half by the crop.

Two limits to know: every participant in the session needs camera video, and
screen shares are not included in the MP4. See
[Exporting to MP4](https://synento.com/docs/guides/recordings-replay.md) for the full
details.

### Wait for it to finish

Check the job until `status` is `completed`:

```bash
curl https://api.synento.com/v1/exports/{jobId} \
  -H "Authorization: Bearer sk_live_xxxxx"
```

```json
{
  "data": {
    "job_id": "8d0c2f0e-…",
    "room_id": "9b1c4e7a2d3f4a8b9c0d1e2f3a4b5c6d",
    "status": "completed",
    "progress_pct": 100,
    "download_url": "/v1/exports/8d0c2f0e-…/download"
  },
  "error": null
}
```

Checking every 10 seconds or so is plenty. If you would rather be told, the
[`export.completed` webhook](https://synento.com/docs/guides/webhooks.md) fires when an export finishes.
Its payload names the session (`session_id`) but not the export and carries
no link to the file. To get the job id, repeat the same export request: it
returns the finished job (`"reused": true`) without encoding or charging again.

### Make the file reachable

The `download_url` needs your secret API key, and JSON2Video cannot send one.
Download the file yourself, then host it at a short-lived link. With S3:

```bash
curl https://api.synento.com/v1/exports/{jobId}/download \
  -H "Authorization: Bearer sk_live_xxxxx" \
  --output session.mp4

aws s3 cp session.mp4 s3://your-bucket/clips/session.mp4
aws s3 presign s3://your-bucket/clips/session.mp4 --expires-in 3600
```

The last command prints a signed URL. That is the `SESSION_MP4_URL` used
below. On Cloudflare R2, add `--endpoint-url https://<account-id>.r2.cloudflarestorage.com`
to both `aws s3` commands; everything else is the same. An hour is enough, since JSON2Video only needs it while the render
runs. Never put your Synento API key in a URL.

## 2. Pick the moments

JSON2Video cuts the video where you tell it to. It does not choose the
moments for you, so this step happens before the render.

**Transcribe the MP4 with timestamps.** The exported MP4 mixes everyone's
audio into one track. Transcribe that file rather than anything else, so the
times you get are times in the file you will cut. Any speech-to-text service
that returns segment or word timestamps works: OpenAI Whisper, Deepgram,
AssemblyAI, ElevenLabs Speech to Text, and others.

**Choose two or three segments** of 8–20 seconds each. You can do it by hand,
or give the transcript to an LLM:

```text
Below is the transcript of a recorded call, with start and end times in seconds.
Pick the 3 moments that best summarise the call for someone who did not attend.
Each moment must be a complete sentence or answer, between 8 and 20 seconds long.
Return only JSON: [{"start": 12.4, "end": 25.1, "why": "..."}]

<transcript>
```

Move each start about 0.3 seconds earlier and each end about 0.3 seconds later,
so no word is clipped: transcript timestamps often end a little before the
speech does. When the next person starts talking straight away, end the cut
where their first word begins instead, or the clip picks up the start of it.

## 3. Render the clip

Each moment becomes one scene. In each scene, `seek` is where the cut starts
in the MP4, in seconds, and `duration` is how long it lasts. `resize: "cover"`
fills the vertical frame, and `position: "center-center"` makes the crop take
the middle of a landscape export. Leave it out and JSON2Video keeps the left
edge instead, showing the thumbnails and cutting off the person in focus. The `subtitles` element sits at movie level: it
transcribes the finished clip and burns in the captions, so you do not need to
send the transcript again.

Save this as `clip.json`:

```json
{
  "resolution": "instagram-story",
  "quality": "high",
  "scenes": [
    {
      "elements": [
        { "type": "video", "src": "SESSION_MP4_URL", "seek": 2.5, "duration": 10.6, "resize": "cover", "position": "center-center" }
      ]
    },
    {
      "elements": [
        { "type": "video", "src": "SESSION_MP4_URL", "seek": 59.7, "duration": 11, "resize": "cover", "position": "center-center" }
      ]
    },
    {
      "elements": [
        { "type": "video", "src": "SESSION_MP4_URL", "seek": 104.3, "duration": 9.8, "resize": "cover", "position": "center-center" }
      ]
    }
  ],
  "elements": [
    {
      "type": "subtitles",
      "settings": {
        "style": "classic-progressive",
        "position": "bottom-center",
        "max-words-per-line": 3,
        "font-size": 70
      }
    }
  ]
}
```

`instagram-story` is 1080×1920. For other shapes, use `full-hd` (1920×1080)
for a horizontal clip, from a landscape export, or `squared` for 1:1.

Send it to JSON2Video:

```bash
curl -X POST "https://api.json2video.com/v2/movies" \
  -H "x-api-key: YOUR_JSON2VIDEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d @clip.json
```

The response contains a `project` id:

```json
{ "success": true, "project": "bfLEfgAXt91xaS5U", "timestamp": "2026-10-23T11:01:24.023Z" }
```

Rendering runs in the background, so check every 10 seconds or so until
`movie.status` is `done` (or `error`, with the reason in `movie.message`):

```bash
curl "https://api.json2video.com/v2/movies?project=PROJECT_ID" \
  -H "x-api-key: YOUR_JSON2VIDEO_API_KEY"
```

```json
{
  "success": true,
  "movie": {
    "status": "done",
    "url": "https://json2video-cdn1.s3.amazonaws.com/clients/…/renders/….mp4",
    "duration": 31.8,
    "width": 1080,
    "height": 1920
  }
}
```

`movie.url` is the finished clip. A 30-second clip took about 20 seconds to
render. You can then delete the copy you uploaded in step 1.

### Cost

- **JSON2Video** bills per second of finished video, rounded up: a
  31.8-second clip uses 32 credits, however long the original session was.
- **Synento** counts only the export, in exported participant-minutes: each
  person's time in the recording. A 2-minute call with 2 people is 4. Plans
  include 300 a month on Free and 3,000 on Pro, then $0.004 each on Pro.
  Asking for the same export again costs nothing.

## Doing it with a coding agent

Both services have MCP servers, so an agent such as Claude Code or Cursor can
do most of this for you. Connect both:

```bash
claude mcp add --transport http synento https://api.synento.com/mcp
npx -y @json2video/cli mcp install claude
```

Then run `/mcp` in Claude Code and choose **synento** to sign in. See
[Connect your agent](https://synento.com/docs/guides/mcp.md) for other editors.

Synento's MCP server can find the session (`list_sessions`) and show what was
recorded (`get_session_manifest`), but it does not start exports. The key it
creates for your app (`rk_live_…`) cannot export either. So the agent also
needs your project's secret key: put it in an environment variable such as
`SYNENTO_API_KEY` rather than pasting it into the chat, and tell the agent
where it may upload the MP4.

Then ask, for example: *"Find yesterday's interview session in Synento.
Export it with the presenter layout focused on the guest, using
SYNENTO_API_KEY (vertical if they were on a phone, landscape otherwise), upload
the MP4 to my S3 bucket with a one-hour link, pick the three best answers from
a transcript, and render a vertical highlight clip with subtitles through
JSON2Video."*

## Variations

- **Branding**: add an `image` element (your logo) at movie level, or a short
  title scene at the start with a `text` element.
- **Follow the speaker**: for an interview, export once per person
  (`focus=alice`, then `focus=bob`) and cut each moment from the export of
  whoever is talking, so the person speaking always fills the frame. Each
  export counts its exported participant-minutes, so two exports cost twice
  as much on the Synento side.
- **One clip per moment**: send one render per segment instead of three
  scenes in one movie, for a set of short quotes.
- **Subtitle style and language**: see JSON2Video's
  [subtitles reference](https://json2video.com/docs/v2/reference/json-syntax/element/subtitles)
  for styles, colours and translation.
- **Whole session with captions**: one scene with the whole MP4
  (`"duration": -1`) and the subtitles element give a captioned copy of the
  call.

## Reference

- [Exporting to MP4](https://synento.com/docs/guides/recordings-replay.md): every export
  option and limit
- [Webhooks](https://synento.com/docs/guides/webhooks.md): the `export.completed` event
- [JSON2Video quickstart](https://json2video.com/docs/v2/getting-started/quickstart)
- [Video element](https://json2video.com/docs/v2/reference/json-syntax/element/video)
  (`seek`, `duration`, `resize`, `crop`)
- [Subtitles element](https://json2video.com/docs/v2/reference/json-syntax/element/subtitles)
- [JSON2Video MCP server](https://json2video.com/docs/v2/help-for-ai-agents/mcp-server)
