Setup Sounds
Integrate LotsOfSounds audio into your video editor via a server-side proxy
RVE ships with a built-in LotsOfSounds audio adaptor. It works through a proxy pattern. Your server holds the API key, the editor calls your local routes, never the LotsOfSounds API directly.
Why a proxy?
The editor runs in the browser. If you called the LotsOfSounds API directly from the client, your API key would be exposed in network requests for anyone to steal. By routing through your own server, the key stays secret and never leaves your backend.
How it works
Editor UI → /api/sounds/search?q=... → Your server → api.lotsofsounds.com
Editor UI → /api/sounds/stream/[id] → Your server → api.lotsofsounds.comThe adaptor is included in the default audio adaptors automatically. You just need to set up two server-side proxy routes.
Step 1: Get a LotsOfSounds API key
Sign up at lotsofsounds.com and get an API key. Add it to your environment:
NEXT_LOTSOFSOUNDS_API_KEY=your_api_key_hereStep 2: Create the search proxy route
Create app/api/sounds/search/route.ts:
import { NextRequest, NextResponse } from 'next/server';
const LOTSOFSOUNDS_API_URL = 'https://api.lotsofsounds.com';
export async function GET(requst) {
const apiKey = process.env.NEXT_LOTSOFSOUNDS_API_KEY;
if (!apiKey) {
return NextResponse.json({ error: 'API key not configured' }, { status: 500 });
}
const { searchParams } = new URL(request.url);
const params = new URLSearchParams();
const q = searchParams.get('q');
if (q) params.set('q', q);
params.set('limit', searchParams.get('limit') || '20');
params.set('page', searchParams.get('page') || '1');
const response = await fetch(
`${LOTSOFSOUNDS_API_URL}/api/v1/sounds?${params.toString()}`,
{ headers: { 'x-api-key': apiKey } }
);
if (!response.ok) {
return NextResponse.json(
{ error: `API error: ${response.status}` },
{ status: response.status }
);
}
return NextResponse.json(await response.json());
}Step 3: Create the stream proxy route
Create app/api/sounds/stream/[id]/route.ts:
import { NextRequest, NextResponse } from 'next/server';
const LOTSOFSOUNDS_API_URL = 'https://api.lotsofsounds.com';
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const apiKey = process.env.NEXT_LOTSOFSOUNDS_API_KEY;
if (!apiKey) {
return NextResponse.json({ error: 'API key not configured' }, { status: 500 });
}
const { id } = await params;
// Get signed download URL
const downloadResponse = await fetch(
`${LOTSOFSOUNDS_API_URL}/api/v1/sounds/${encodeURIComponent(id)}/download`,
{ headers: { 'x-api-key': apiKey } }
);
if (!downloadResponse.ok) {
return NextResponse.json(
{ error: `API error: ${downloadResponse.status}` },
{ status: downloadResponse.status }
);
}
const data = await downloadResponse.json();
const signedUrl = data?.data?.download_url;
if (!signedUrl) {
return NextResponse.json({ error: 'No download URL returned' }, { status: 502 });
}
// Pipe audio bytes to client
const audioResponse = await fetch(signedUrl);
const contentType = audioResponse.headers.get('content-type') || 'audio/mpeg';
return new NextResponse(audioResponse.body, {
status: 200,
headers: {
'Content-Type': contentType,
'Cache-Control': 'public, max-age=3600',
},
});
}Step 4: That's it
The default audio adaptors already include LotsOfSounds. When you pass no audio key in your adaptors prop, RVE uses it automatically. The sounds panel will show up in the editor sidebar with search and pagination.
If you're already passing custom adaptors, the LotsOfSounds adaptor is available as a named export:
import { lotsofsoundsAudioAdaptor } from '@reactvideoeditor/react-video-editor/adaptors/lotsofsounds-audio-adaptor';
<ReactVideoEditor
adaptors={{
audio: [lotsofsoundsAudioAdaptor],
// ...other adaptors
}}
/>