# Media sync CLI commands

> Canonical HTML: https://screenrig.ai/docs/cli/media-sync

Keep a media folder in step with SharePoint, OneDrive, Dropbox or Google Drive: add accounts, create syncs, run them and read their results. Every command here runs as described in the [CLI reference](https://screenrig.ai/docs/cli.md): global flags, JSON output, exit codes, revisions and retries.

## Media sync

A media sync keeps a media folder in step with a SharePoint, OneDrive for work, Dropbox or Google Drive folder. Each run imports the images (png, jpeg, webp, gif), videos (mp4, webm) and audio (mp3) directly inside the source folder; subfolders are ignored. A changed file replaces its bytes under the same media ID, so every playlist that plays it updates, and a file removed or moved out at the source leaves play: its media is deleted or, while a screen still shows it, moved to a `Removed` subfolder and deleted when nothing holds it. Other files are listed as skipped with the reason: show an Office file or PDF with a document link in a playlist, and export MOV and the like as MP4 H.264. A playlist plays the folder with a `by:folder` selector.

Every sync reads through an account of the project. An account ID starts `msa_` and a sync ID `msy_`. `media sync account add microsoft365` stores your own Microsoft Entra app, or names a Microsoft [connection](https://screenrig.ai/docs/connections.md) of the project; `media sync account add dropbox` prints a one-time link for the person who owns the Dropbox account; `media sync account add google-drive` reads the folders shared with a service account's address, screenRIG's or your own. Test the account, then create a sync from a folder's address: it is due at once.

Give a client secret with `--secret-file FILE` and a Google Drive key with `--key-file FILE`, or `-` for stdin, never as an argument. Secrets are sealed on the server and shown back only as `data.secret` `{set, hint}`. Reading needs Read access, and every change needs Manage access.

### `media sync account add microsoft365`

Add your own Microsoft Entra app, or a Microsoft connection of the project, so a sync can read a SharePoint or OneDrive for work folder.

```console
media sync account add microsoft365 --name NAME
    (--tenant-id TENANT --client-id ID --secret-file FILE | --connection-id ID)
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--name NAME` | string | yes | none | 1 to 80 characters. |
| `--tenant-id TENANT` | string | without `--connection-id` | none | Your organization's directory (tenant) ID, or its primary domain such as `contoso.onmicrosoft.com`; never `common`, `organizations` or `consumers`. Together with `--client-id` and `--secret-file`. |
| `--client-id ID` | string | without `--connection-id` | none | The app registration's application (client) ID, a GUID. |
| `--secret-file FILE` | string | without `--connection-id` | none | Read the client secret's Value from this file, or `-` for stdin (never an argument); the file holds only the Value. |
| `--connection-id ID` | string | without `--tenant-id` | none | Sign in through a Microsoft connection (`pcn_…`) of the project, in either mode, instead of `--tenant-id`, `--client-id` and `--secret-file`. Not with them. |

```console
screenrig media sync account add microsoft365 --name Contoso --tenant-id contoso.onmicrosoft.com --client-id 0b1d2f3a-4c5e-4f60-8a7b-9c0d1e2f3a4b --secret-file secret.txt
screenrig media sync account add microsoft365 --name Contoso --connection-id pcn_01EXAMPLECONNECTION0000
```

In the Microsoft Entra admin center, register a single-tenant app with no redirect URI, add a client secret (copy its Value, not its Secret ID), add the Microsoft Graph application permission `Sites.Selected` (then grant the app read access to each site) or `Files.Read.All`, and grant admin consent. The app belongs to this project. Run `media sync account test` next.

### `media sync account add dropbox`

Add a Dropbox account and print the one-time link its owner opens, signed in to Dropbox, to connect it.

```console
media sync account add dropbox --name NAME [--app-key KEY]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--name NAME` | string | yes | none | 1 to 80 characters. |
| `--app-key KEY` | string | no | screenRIG's Dropbox app | The app key of your own Dropbox app: 1 to 64 letters and digits, never its app secret. |

```console
screenrig media sync account add dropbox --name "Marketing Dropbox"
screenrig media sync account add dropbox --name "Marketing Dropbox" --app-key YOURAPPKEY
```

`data.authorize_url` is the link and `data.authorize_expires_at` its expiry. The CLI never opens a browser: send the link to the person who owns the Dropbox account, who allows read-only access (`files.metadata.read`, `files.content.read`, `account_info.read`, `sharing.read`). Run `media sync account show` until `data.state` is `ready` (it starts as `pending_consent`), then `media sync create dropbox`. Your own Dropbox app needs those permissions enabled and the redirect URI that the output prints.

### `media sync account add google-drive`

Add a Google Drive account, ready at once, and print the service account address that folders are shared with.

```console
media sync account add google-drive --name NAME [--key-file FILE]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--name NAME` | string | yes | none | 1 to 80 characters. |
| `--key-file FILE` | string | no | screenRIG's service account | Read your own Google Cloud service account's JSON key from this file, or `-` for stdin (never an argument). |

```console
screenrig media sync account add google-drive --name "Marketing Drive"
screenrig media sync account add google-drive --name "Marketing Drive" --key-file key.json
```

`data.config.service_account_email` is the address to share each folder with; Viewer is enough. Through screenRIG's service account a folder syncs only when a member of this project with a verified email shared it or owns it (`media_sync_sharer_not_member` otherwise). With your own key, any folder shared with the service account syncs.

### `media sync account list`

List this project's media sync accounts with their kind, state and last test; no secret is returned.

```console
media sync account list
```

No parameters.

```console
screenrig media sync account list
```

### `media sync account show`

Inspect one account: its tenant and client ID, state, masked secret and last test.

```console
media sync account show <id>
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The account (`msa_…`). |

```console
screenrig media sync account show msa_01EXAMPLEACCOUNT0000000
```

A Dropbox account also shows who connected it and its `app_key`; a Google Drive account shows its `service_account_email`.

### `media sync account update`

Rename an account, change a Microsoft app's tenant, application ID or client secret, or replace a Google Drive account's own key.

```console
media sync account update <id> [--name NAME] [--tenant-id TENANT] [--client-id ID]
    [--secret-file FILE | --key-file FILE] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The account (`msa_…`). |
| `--name NAME` | string | no | unchanged | Rename the account. |
| `--tenant-id TENANT` | string | no | unchanged | The tenant's directory ID or primary domain. |
| `--client-id ID` | string | no | unchanged | The app registration's application (client) ID. |
| `--secret-file FILE` | string | no | unchanged | Read the new client secret's Value from this file, or `-` for stdin; it replaces the stored secret. An omitted secret is kept. |
| `--key-file FILE` | string | no | unchanged | Read a Google Drive account's own JSON key from this file, or `-` for stdin; it must belong to the same service account. Not with `--secret-file`. |
| `--expect-rev REVISION` | integer | no | none | Refuse the change unless the account is at this revision (`revision_conflict`, exit 6). |

```console
screenrig media sync account update msa_01EXAMPLEACCOUNT0000000 --secret-file new-secret.txt
screenrig media sync account update msa_01EXAMPLEACCOUNT0000000 --name "Contoso tenant" --expect-rev 2
```

At least one change is required. A change of credentials clears `last_test`: test the account again. Entra client secrets expire, so replace the secret here before it does.

### `media sync account connect`

Make a new one-time link to connect, or reconnect, a Dropbox account.

```console
media sync account connect <id>
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The account (`msa_…`). |

```console
screenrig media sync account connect msa_01EXAMPLEACCOUNT0000000
```

`data.authorize_url` and `data.authorize_expires_at` carry the link, which replaces the earlier one. Send it to the person who owns the Dropbox account. Use it when the person did not finish or the account is `reconnect_required` (Dropbox no longer honors the connection). A connected account stays connected until the new consent completes, and another Dropbox account signing in takes over the connection.

### `media sync account test`

Check an account: a Microsoft app's sign-in and Graph permissions, or the connection or key of a Dropbox or Google Drive account.

```console
media sync account test <id>
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The account (`msa_…`). |

```console
screenrig media sync account test msa_01EXAMPLEACCOUNT0000000
```

The answer is stored as `last_test`. For a Microsoft app it reports `credentials` (Microsoft issued a token; a refusal carries its `AADSTS` code, such as `AADSTS7000215` for a secret that is the ID rather than the Value) and `permissions` (the Graph application permissions the token carries). `Sites.Selected` alone is a warning: each site still needs its grant, and a sharing link needs `Files.Read.All`. The test does not judge a site's grant or a folder: `media sync create` reads the folder you name. A failed check is `data.ok` false with exit 0.

### `media sync account delete`

Delete an account no sync uses.

```console
media sync account delete <id> [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The account (`msa_…`). |
| `--expect-rev REVISION` | integer | no | none | Refuse the delete unless the account is at this revision (`revision_conflict`, exit 6). |

```console
screenrig media sync account delete msa_01EXAMPLEACCOUNT0000000
```

While syncs use the account the answer is `resource_conflict` (exit 5), naming them: delete those first.

### `media sync create sharepoint`

Sync a SharePoint or OneDrive for work folder into a media folder.

```console
media sync create sharepoint --account-id ID --url URL [--folder-id ID] [--every DURATION] [--name NAME]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--account-id ID` | string | yes | none | The account to read through (`msa_…`). |
| `--url URL` | string | yes | none | The folder's SharePoint address, such as `https://contoso.sharepoint.com/sites/Marketing/Shared%20Documents/Lobby%20Signs`, which works with `Sites.Selected` once the site is granted, or its sharing link (Share, Copy link), which needs `Files.Read.All`. Personal OneDrive (`onedrive.live.com`, `1drv.ms`) cannot be read with an organization app. |
| `--folder-id ID` | string | no | a new media folder named after the source folder | The media folder (`mfd_…`) the files land in. |
| `--every DURATION` | string | no | `15m` | How often to look for changes, 5 minutes to 24 hours: `15m`, `1h`, `6h`, or plain seconds (300 to 86400). |
| `--name NAME` | string | no | the source folder's name | 1 to 80 characters. |

```console
screenrig media sync create sharepoint --account-id msa_01EXAMPLEACCOUNT0000000 --url https://contoso.sharepoint.com/sites/Marketing/Shared%20Documents/Lobby%20Signs
screenrig media sync create sharepoint --account-id msa_01EXAMPLEACCOUNT0000000 --url "https://contoso.sharepoint.com/:f:/s/Marketing/EabcDEF" --folder-id mfd_01EXAMPLEFOLDER000000000 --every 1h --name "Lobby signs"
```

A folder Microsoft refuses is `media_sync_source_refused` (exit 5), with the permission to grant; nothing is stored.

### `media sync create dropbox`

Sync a Dropbox folder into a media folder.

```console
media sync create dropbox --account-id ID --url URL|PATH [--folder-id ID] [--every DURATION] [--name NAME]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--account-id ID` | string | yes | none | The connected Dropbox account to read through (`msa_…`). |
| `--url URL` | string | yes | none | The folder's Dropbox address (`https://www.dropbox.com/home/...`), a shared folder link the account has added to its Dropbox, or a path that starts with `/`. A team space folder is read from the team's root. |
| `--folder-id ID` | string | no | a new media folder named after the source folder | The media folder (`mfd_…`) the files land in. |
| `--every DURATION` | string | no | `15m` | How often to look for changes, 5 minutes to 24 hours: `15m`, `1h`, `6h`, or plain seconds (300 to 86400). |
| `--name NAME` | string | no | the source folder's name | 1 to 80 characters. |

```console
screenrig media sync create dropbox --account-id msa_01EXAMPLEACCOUNT0000000 --url https://www.dropbox.com/home/Marketing/Lobby%20Signs
screenrig media sync create dropbox --account-id msa_01EXAMPLEACCOUNT0000000 --url /Marketing/Lobby --folder-id mfd_01EXAMPLEFOLDER000000000 --every 1h --name "Lobby signs"
```

Each run continues from Dropbox's saved position in the folder and reads only what changed. A folder the account cannot open is `media_sync_source_refused`, and a connection Dropbox no longer honors is `dropbox_reconnect_required` (`media sync account connect`): both exit 5, nothing stored.

### `media sync create google-drive`

Sync a Google Drive folder shared with an account's service account into a media folder.

```console
media sync create google-drive --account-id ID --url URL|ID [--folder-id ID] [--every DURATION] [--name NAME]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--account-id ID` | string | yes | none | The Google Drive account to read through (`msa_…`). |
| `--url URL` | string | yes | none | The folder's address (`https://drive.google.com/drive/folders/ID`), or its ID. Share the folder with the account's `service_account_email` first; Viewer is enough. |
| `--folder-id ID` | string | no | a new media folder named after the source folder | The media folder (`mfd_…`) the files land in. |
| `--every DURATION` | string | no | `15m` | How often to look for changes, 5 minutes to 24 hours: `15m`, `1h`, `6h`, or plain seconds (300 to 86400). |
| `--name NAME` | string | no | the source folder's name | 1 to 80 characters. |

```console
screenrig media sync create google-drive --account-id msa_01EXAMPLEACCOUNT0000000 --url https://drive.google.com/drive/folders/1AbCdEfGhIjKlMnOpQrStUvWxYz --folder-id mfd_01EXAMPLEFOLDER000000000 --every 1h
screenrig media sync create google-drive --account-id msa_01EXAMPLEACCOUNT0000000 --url 1AbCdEfGhIjKlMnOpQrStUvWxYz
```

Through screenRIG's service account the folder syncs only when a member of this project with a verified email shared it or owns it (`media_sync_sharer_not_member`, exit 3, nothing stored). Every run checks that again, and a folder that loses such a sharer stops the sync in state `error` with its media kept: share it again from a member's Google account, then run `media sync update ID --resume`. Google Docs, Sheets and Slides files are skipped as `unsupported_type`. A folder the address cannot open is `media_sync_source_refused` (exit 5): share it with the service account.

### `media sync list`

List this project's media syncs with their media folder, cadence, state and last run status.

```console
media sync list
```

No parameters.

```console
screenrig media sync list
```

### `media sync show`

Inspect one sync and the summary of its last run.

```console
media sync show <id>
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The sync (`msy_…`). |

```console
screenrig media sync show msy_01EXAMPLESYNC000000000
```

`data.last_run` carries `status` (`ok`, `partial` or `error`), `added`, `updated`, `removed`, `pending_delete` (removed files a screen still holds, waiting in the `Removed` folder), `skipped_total` and `skipped`, the first 20 skipped files with each file's reason (`unsupported_type`, `too_large`, `storage`, `subfolder`, `download_failed`, `unreadable`, `in_use`); a failed run carries `error` with a `code` and a `detail` that name the fix. `data.source` adds `path` for Dropbox and `shared_by` for Google Drive.

A sync in state `error` needs a repair. Its media folder was deleted: point it at another with `media sync update --folder-id`. Its source folder was deleted or moved: delete the sync and create one. For Google Drive through screenRIG's service account, the folder lost its verified sharer (`sharer_not_member`): share it again from a project member's Google account, then `media sync update ID --resume`. A Dropbox run fails with `reconnect_required` when Dropbox stops honoring the connection (`media sync account connect`).

### `media sync update`

Change a sync's name, cadence or media folder, or pause and resume it.

```console
media sync update <id> [--name NAME] [--every DURATION] [--folder-id ID]
    [--pause | --resume] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The sync (`msy_…`). |
| `--name NAME` | string | no | unchanged | Rename the sync. |
| `--every DURATION` | string | no | unchanged | How often to look for changes, 5 minutes to 24 hours. |
| `--folder-id ID` | string | no | unchanged | Fill this media folder (`mfd_…`) instead. The next run reads the whole source again and places every synced file in it. |
| `--pause` | boolean | no | off | Stop running until resumed. Not with `--resume`. |
| `--resume` | boolean | no | off | Run again; also restarts a sync an error stopped. Not with `--pause`. |
| `--expect-rev REVISION` | integer | no | none | Refuse the change unless the sync is at this revision (`revision_conflict`, exit 6). |

```console
screenrig media sync update msy_01EXAMPLESYNC000000000 --every 1h
screenrig media sync update msy_01EXAMPLESYNC000000000 --pause
screenrig media sync update msy_01EXAMPLESYNC000000000 --folder-id mfd_01EXAMPLEFOLDER000000000 --expect-rev 3
```

At least one change is required.

### `media sync run`

Run a sync now instead of at its next time.

```console
media sync run <id>
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The sync (`msy_…`). |

```console
screenrig media sync run msy_01EXAMPLESYNC000000000
```

The sync runs within about 30 seconds, and `media sync show` then shows its last run. A paused sync must be resumed first.

### `media sync delete`

Stop a sync; its media and folder stay.

```console
media sync delete <id> [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The sync (`msy_…`). |
| `--expect-rev REVISION` | integer | no | none | Refuse the delete unless the sync is at this revision (`revision_conflict`, exit 6). |

```console
screenrig media sync delete msy_01EXAMPLESYNC000000000
```

The sync forgets which source file became which media. The imported media and the media folder stay, and nothing is removed.

## Other command groups

- [Projects](https://screenrig.ai/docs/cli/projects.md)
- [Service clients](https://screenrig.ai/docs/cli/service-clients.md)
- [Help and support](https://screenrig.ai/docs/cli/help.md)
- [Media](https://screenrig.ai/docs/cli/media.md)
- [Playlists](https://screenrig.ai/docs/cli/playlists.md)
- [Cards](https://screenrig.ai/docs/cli/cards.md)
- [Applications](https://screenrig.ai/docs/cli/applications.md)
- [Screens](https://screenrig.ai/docs/cli/screens.md)
- [Schedules](https://screenrig.ai/docs/cli/schedules.md)
- [Campaigns](https://screenrig.ai/docs/cli/campaigns.md)
- [Device health](https://screenrig.ai/docs/cli/device.md)
- [Reviews and notes](https://screenrig.ai/docs/cli/reviews.md)
- [Notifications](https://screenrig.ai/docs/cli/notifications.md)
- [Reports](https://screenrig.ai/docs/cli/reports.md)
- [Data sources](https://screenrig.ai/docs/cli/data-sources.md)
- [BI dashboards](https://screenrig.ai/docs/cli/bi.md)
- [Triggers](https://screenrig.ai/docs/cli/triggers.md)
- [Fleet links](https://screenrig.ai/docs/cli/fleet-links.md)
- [Advertising](https://screenrig.ai/docs/cli/ads.md)
