# Integrate Soundstripe Audio Library

Integrate Soundstripe’s vast library of royalty-free audio tracks directly into CE.SDK, enabling users to search and add high-quality music to their designs.

![Soundstripe audio integration](/docs/cesdk/_astro/browser.hero.DS5lJXF9_LSMtQ.webp)

10 mins

estimated time

Live Demo[

Download](https://github.com/imgly/cesdk-web-examples/archive/refs/heads/main.zip)[

StackBlitz](https://stackblitz.com/~/github.com/imgly/cesdk-web-examples)[

GitHub](https://github.com/imgly/cesdk-web-examples)

Soundstripe provides a vast library of high-quality, royalty-free audio tracks through their API. This guide shows you how to integrate Soundstripe’s audio search and browsing capabilities directly into CE.SDK using the official `@imgly/plugin-soundstripe-web` plugin. You’ll learn how to set up Soundstripe API authentication (including proxy server requirements for production), implement search and discovery features, configure the asset library UI, and handle automatic URI refresh for expired audio links.

```
import type { EditorPlugin, EditorPluginContext } from '@cesdk/cesdk-js';import SoundstripePlugin from '@imgly/plugin-soundstripe-web';import { refreshSoundstripeAudioURIs } from '@imgly/plugin-soundstripe-web';import packageJson from './package.json';
/** * CE.SDK Plugin: Soundstripe Audio Integration * * Demonstrates integrating Soundstripe's audio library into CE.SDK: * - Adding the Soundstripe plugin * - Configuring API authentication (direct or proxy) * - Adding Soundstripe to the audio asset library * - Automatic URI refresh for expired audio links * - Manual URI refresh utility */class Example implements EditorPlugin {  name = packageJson.name;  version = packageJson.version;
  async initialize({ cesdk }: EditorPluginContext): Promise<void> {    if (!cesdk) {      throw new Error('CE.SDK instance is required for this plugin');    }
    const engine = cesdk.engine;
    // Load default assets and create a basic scene    await cesdk.addDefaultAssetSources();    await cesdk.addDemoAssetSources({ sceneMode: 'Video' });
    // Create a video scene for demonstrating audio    await cesdk.createVideoScene();
    // Configure Soundstripe plugin with proxy server    // The proxy securely handles API authentication without exposing keys in the frontend    // Set up your own proxy server following:    // https://docs.soundstripe.com/docs/integrating-soundstripes-content-into-your-application    const proxyUrl = import.meta.env.VITE_SOUNDSTRIPE_PROXY_URL || 'https://your-proxy-server.example.com';
    await cesdk.addPlugin(      SoundstripePlugin({        baseUrl: proxyUrl      })    );
    // Configure localization for the asset library    cesdk.i18n.setTranslations({      en: {        'libraries.soundstripe.label': 'Soundstripe'      }    });
    // Configure the asset library UI with a dedicated Soundstripe dock entry    cesdk.ui.addAssetLibraryEntry({      id: 'soundstripe',      sourceIds: ['ly.img.audio.soundstripe'],      previewLength: 6,      gridColumns: 2,      gridItemHeight: 'auto',      cardLabel: (assetResult) => assetResult.label    });
    // Add Soundstripe to the existing Audio asset library    cesdk.ui.updateAssetLibraryEntry('ly.img.audio', {      sourceIds: ({ currentIds }) => [...currentIds, 'ly.img.audio.soundstripe']    });
    // Add Soundstripe as the first button in the dock with a separator    cesdk.ui.setDockOrder([      {        id: 'ly.img.assetLibrary.dock',        key: 'soundstripe',        label: 'libraries.soundstripe.label',        entries: ['soundstripe']      },      { id: 'ly.img.separator' },      ...cesdk.ui.getDockOrder()    ]);
    // Example: Manual URI refresh utility    // This is useful if you need to manually refresh expired URIs    // The plugin handles automatic refresh during scene loading and playback    const handleManualRefresh = async () => {      await refreshSoundstripeAudioURIs(engine, { baseUrl: proxyUrl });    };
    // You can call this function when needed    // For example, when loading a scene or before playback    // handleManualRefresh();  }}
export default Example;
```

This guide covers installing the Soundstripe plugin, configuring API authentication with direct access or proxy server, adding Soundstripe to the audio asset library, understanding URI expiration and automatic refresh, and manually triggering URI refresh when needed.

## Prerequisites[#](#prerequisites)

Before integrating Soundstripe, ensure you have:

*   The `@imgly/plugin-soundstripe-web` package installed via npm, yarn, or pnpm
*   A Soundstripe API key from [Soundstripe](https://soundstripe.com/)
*   A proxy server setup to handle API authentication securely

**IMPORTANT**: For production use, you must set up your own proxy server. Follow [Soundstripe’s integration guide](https://docs.soundstripe.com/docs/integrating-soundstripes-content-into-your-application) which covers:

*   **Option 1**: Direct API integration (client-side)
*   **Option 2**: Proxy server setup (recommended for production)

The proxy approach handles authentication securely, prevents exposing API keys in client-side code, ensures CORS compliance, and maintains stable API access.

## Installing the Soundstripe Plugin[#](#installing-the-soundstripe-plugin)

Install the plugin package using a package manager:

Terminal window

```
pnpm add @imgly/plugin-soundstripe-web# oryarn add @imgly/plugin-soundstripe-web# ornpm install @imgly/plugin-soundstripe-web
```

## Configuring the Plugin[#](#configuring-the-plugin)

The Soundstripe plugin requires configuration with either a proxy server (recommended for production) or direct API access (development only).

### Proxy Server Setup (Recommended)[#](#proxy-server-setup-recommended)

Configure the plugin with a proxy server base URL to keep your API key secure:

```
// Configure Soundstripe plugin with proxy server// The proxy securely handles API authentication without exposing keys in the frontend// Set up your own proxy server following:// https://docs.soundstripe.com/docs/integrating-soundstripes-content-into-your-applicationconst proxyUrl = import.meta.env.VITE_SOUNDSTRIPE_PROXY_URL || 'https://your-proxy-server.example.com';
await cesdk.addPlugin(  SoundstripePlugin({    baseUrl: proxyUrl  }));
```

The proxy server handles Soundstripe API authentication server-side, preventing exposure of your API key in the frontend code. This is the recommended approach for both development and production environments.

### Direct API Access (Development Only)[#](#direct-api-access-development-only)

For local development and testing, you can configure the plugin with a direct API key:

```
const apiKey = import.meta.env.VITE_SOUNDSTRIPE_API_KEY;
await cesdk.addPlugin(  SoundstripePlugin({    apiKey,  }),);
```

This approach should not be used in production as it exposes your API key in the frontend code.

## Plugin Configuration Parameters[#](#plugin-configuration-parameters)

The plugin configuration object supports the following parameters:

*   **`apiKey`** (string, conditional): Your Soundstripe API key. Required when using direct API access for development.
*   **`baseUrl`** (string, conditional): Your proxy server base URL. Required when using proxy server for production.

**Note:** Either `apiKey` or `baseUrl` must be provided. You cannot omit both parameters.

## How the Plugin Works[#](#how-the-plugin-works)

The Soundstripe plugin automatically registers an asset source with CE.SDK using `engine.asset.addSource()` internally. The plugin handles all API communication, translates API responses to CE.SDK’s asset format, and manages asset source registration. You don’t need to manually implement the asset source interface—the plugin takes care of everything.

The source ID for Soundstripe is `ly.img.audio.soundstripe`, which the plugin registers automatically when added.

## Adding Soundstripe to the Audio Asset Library[#](#adding-soundstripe-to-the-audio-asset-library)

After adding the plugin, configure how Soundstripe appears in CE.SDK’s asset library panel:

```
// Configure the asset library UI with a dedicated Soundstripe dock entrycesdk.ui.addAssetLibraryEntry({  id: 'soundstripe',  sourceIds: ['ly.img.audio.soundstripe'],  previewLength: 6,  gridColumns: 2,  gridItemHeight: 'auto',  cardLabel: (assetResult) => assetResult.label});
// Add Soundstripe to the existing Audio asset librarycesdk.ui.updateAssetLibraryEntry('ly.img.audio', {  sourceIds: ({ currentIds }) => [...currentIds, 'ly.img.audio.soundstripe']});
// Add Soundstripe as the first button in the dock with a separatorcesdk.ui.setDockOrder([  {    id: 'ly.img.assetLibrary.dock',    key: 'soundstripe',    label: 'libraries.soundstripe.label',    entries: ['soundstripe']  },  { id: 'ly.img.separator' },  ...cesdk.ui.getDockOrder()]);
```

The `addAssetLibraryEntry()` call registers the Soundstripe asset library panel with display settings:

*   `gridColumns`: Number of columns in the grid layout (2 for audio tracks)
*   `gridItemHeight`: Height style for grid items (`'auto'` maintains aspect ratio)
*   `cardLabel`: Function that returns the label to display on each card (shows track title/artist)
*   `previewLength`: Number of preview items to show

The `cardLabel` property is particularly important for audio assets as it makes the track title and artist information always visible on the card, matching the display style of the default Audio library.

The `setDockOrder()` call creates an explicit dock button component by prepending a new `AssetLibraryDockComponent` to the existing dock order.

The dock component structure includes:

*   `id`: Fixed identifier for asset library dock buttons (`'ly.img.assetLibrary.dock'`)
*   `key`: Unique identifier for this specific button (`'soundstripe'`)
*   `label`: Internationalization key for the button label (`'libraries.soundstripe.label'`)
*   `entries`: Array of asset library entry IDs to display when clicked (`['soundstripe']`)

Additionally, we add Soundstripe to the existing Audio asset library using `updateAssetLibraryEntry()`. This provides dual access: users can access Soundstripe tracks both from the dedicated Soundstripe panel and from the Audio library panel. The functional update pattern `({ currentIds }) => [...currentIds, 'ly.img.audio.soundstripe']` appends Soundstripe to the existing sources without replacing them.

The separator component `{ id: 'ly.img.separator' }` adds a visual divider between the Soundstripe button and the default dock buttons, improving UI organization and clarity.

## Understanding URI Expiration[#](#understanding-uri-expiration)

Soundstripe MP3 file URIs expire after a certain time period. This is a security measure implemented by Soundstripe to protect their content. When URIs expire, audio tracks will fail to play or load in the editor. The plugin automatically handles URI refresh to ensure your audio tracks continue to play without interruption.

## Automatic URI Refresh[#](#automatic-uri-refresh)

The plugin includes built-in automatic URI refresh that happens at key moments:

*   When a scene is loaded
*   When the block selection changes
*   Before playback if URIs are expired

The plugin monitors audio blocks in your scene and refreshes expired Soundstripe URIs automatically. No additional configuration is required—this functionality works out of the box.

## Manual URI Refresh[#](#manual-uri-refresh)

In some cases, you may need to manually trigger a URI refresh. The plugin exports a `refreshSoundstripeAudioURIs()` utility function for this purpose:

```
// Example: Manual URI refresh utility// This is useful if you need to manually refresh expired URIs// The plugin handles automatic refresh during scene loading and playbackconst handleManualRefresh = async () => {  await refreshSoundstripeAudioURIs(engine, { baseUrl: proxyUrl });};
// You can call this function when needed// For example, when loading a scene or before playback// handleManualRefresh();
```

This function scans all audio blocks in the current scene, identifies Soundstripe audio tracks with expired URIs, and refreshes them using the configured API key or proxy server. You can call this function when loading a scene from storage, before starting video playback, or when users report audio playback issues.

## Setting Up a Proxy Server[#](#setting-up-a-proxy-server)

For production environments, you should set up a proxy server to handle Soundstripe API requests securely. Follow [Soundstripe’s integration guide](https://docs.soundstripe.com/docs/integrating-soundstripes-content-into-your-application) for detailed proxy setup instructions.

Here’s an example Node.js Express endpoint for creating your own proxy:

```
// Example Node.js proxy endpointapp.use('/api/soundstripe', async (req, res) => {  const response = await fetch(`https://api.soundstripe.com/v1${req.path}`, {    headers: {      Authorization: `Bearer ${process.env.SOUNDSTRIPE_API_KEY}`,      Accept: 'application/vnd.api+json',      'Content-Type': 'application/vnd.api+json',    },  });
  const data = await response.json();  res.json(data);});
```

The proxy server receives requests from your frontend, adds the authentication header with your API key (stored in environment variables), forwards the request to Soundstripe’s API, and returns the response to your frontend. Configure your plugin to use your proxy:

```
await cesdk.addPlugin(  SoundstripePlugin({    baseUrl: 'https://your-domain.com/api/soundstripe',  }),);
```

## Searching and Browsing Audio[#](#searching-and-browsing-audio)

Once configured, the plugin automatically handles search queries through the asset panel. Users can search for audio tracks by keywords, and the plugin fetches results from Soundstripe’s API. The plugin manages pagination, filtering, and all API interactions behind the scenes.

## Adding Audio to Scenes[#](#adding-audio-to-scenes)

To add Soundstripe audio tracks to the scene programmatically, use `engine.asset.apply()`:

```
const sourceId = 'ly.img.audio.soundstripe';const assets = await engine.asset.findAssets(sourceId, {  page: 0,  perPage: 10,});
if (assets.assets.length > 0) {  const audioBlock = await engine.asset.apply(sourceId, assets.assets[0]);  // The audio block is now added to the scene}
```

The plugin ensures URIs are fresh before adding audio to the scene.

## Retrieving Song IDs[#](#retrieving-song-ids)

When users add Soundstripe songs, the plugin stores the song ID as metadata. You can retrieve these IDs programmatically (e.g., during export). This is useful when you need to pass the song ID through the Soundstripe API to generate a code for YouTube video captions or descriptions before publishing:

```
const audioBlocks = cesdk.engine.block.findByType('audio');
audioBlocks.forEach(blockId => {  const songId = cesdk.engine.block.getMetadata(    blockId,    'ly.img.audio.soundstripe.songId',  );
  if (songId) {    console.log('Soundstripe Song ID:', songId);    // Use this songId with Soundstripe API to generate YouTube attribution codes  }});
```

The song ID is stored using the metadata key `'ly.img.audio.soundstripe.songId'` and can be retrieved at any time after the audio has been added to the scene. This allows you to integrate with Soundstripe’s attribution API or include required attribution information in your exported content.

## Testing the Integration[#](#testing-the-integration)

Test both search functionality and audio browsing through the asset library panel:

1.  Open the audio asset library panel in CE.SDK
2.  Navigate to the Soundstripe source
3.  Search for audio tracks by keyword
4.  Preview audio tracks in the panel
5.  Add an audio track to the scene
6.  Verify the audio plays correctly

If the audio asset library doesn’t show Soundstripe, verify the source ID was added correctly using `getAssetLibraryEntry()`.

## Troubleshooting[#](#troubleshooting)

Common issues and solutions:

**API authentication errors**: Verify your API key is correct or that your proxy server URL is accessible and properly configured.

**Plugin not registering the asset source**: Check that the plugin configuration includes either `apiKey` or `baseUrl`. Verify the plugin was added using `cesdk.addPlugin()` before trying to use the source.

**Audio not playing**: Check that URIs haven’t expired. Call `refreshSoundstripeAudioURIs()` manually to refresh them. Verify the Soundstripe API is accessible from your environment.

**Proxy server CORS issues**: Ensure your proxy server includes proper CORS headers. Add `Access-Control-Allow-Origin` headers to your proxy responses.

**Missing audio tracks in asset library**: Verify the Soundstripe source ID (`ly.img.audio.soundstripe`) was added to the audio entry’s `sourceIds` array using `updateAssetLibraryEntry()`.

## API Reference[#](#api-reference)

| Method | Category | Purpose |
| --- | --- | --- |
| `cesdk.addPlugin()` | Plugin | Add the Soundstripe plugin to CE.SDK |
| `engine.asset.findAllSources()` | Asset | List all registered asset sources |
| `cesdk.ui.getAssetLibraryEntry()` | UI | Get asset library entry configuration |
| `cesdk.ui.updateAssetLibraryEntry()` | UI | Update asset library entry with Soundstripe source |
| `engine.asset.apply()` | Asset | Add Soundstripe audio to the scene |
| `engine.block.findByType()` | Block | Find blocks by type (e.g., audio blocks) |
| `engine.block.getMetadata()` | Block | Retrieve metadata from a block (e.g., song ID) |
| `refreshSoundstripeAudioURIs()` | Utility | Manually refresh expired audio URIs |

## Next Steps[#](#next-steps)

*   [Customize Asset Library](sveltekit/import-media/asset-panel/customize-c9a4de/) — Configure asset panels and UI
*   [Asset Library Basics](sveltekit/import-media/asset-panel/basics-f29078/) — Understand asset sources
*   [Integrate Unsplash Images](sveltekit/import-media/from-remote-source/unsplash-8f31f0/) — Add stock image sources
*   [IMG.LY Premium Assets](sveltekit/import-media/from-remote-source/imgly-premium-assets-eb1688/) — Access premium stock content
*   [Import Media Concepts](sveltekit/import-media/concepts-5e6197/) — Learn core import concepts

---



[Source](https:/img.ly/docs/cesdk/sveltekit/import-media/from-remote-source/remote-asset-484685)