Docs / Files, documents and media

Audio and video tools API

Convert, trim, draw a waveform or take a frame, with ffmpeg.

Files in, files out, nothing kept. Each counts as 30 against the rate limit. Needs a free API key once keys are required (see /keys).

Base URL https://api.dharun.devNo key needed for most600 units a minute, 3000 with a free keyThis page as Markdown

Convert audio or video

POST/v1/media/convert

To MP3, WAV, OGG (Opus), M4A, FLAC, MP4, WebM or an animated GIF. Options go in the query string, or as form fields when the file is sent as multipart/form-data.

Send: Audio or video ffmpeg can read (MP3, WAV, M4A, OGG, FLAC, MP4, MOV, WebM, MKV...), up to 10 MB; the first 10 minutes are used. Post the file as the request body, or as multipart/form-data. Try it with this sample.

The answer returns the audio itself; errors are JSON as everywhere else.

Model endpoint: it will need a free API key, sent as Authorization: Bearer <key> or X-API-Key. Until the date on API keys it answers without one and says so in the X-Key-Notice header. With a key: 500 model requests a day.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
formatquery, requiredWhat to make. One of: mp3, wav, ogg, m4a, flac, mp4, webm, gif.

curl

# a sample to try: https://api.dharun.dev/samples/speech.mp3
curl -F "[email protected]" -o speech.wav "https://api.dharun.dev/v1/media/convert?format=wav&utm_medium=docs"

JavaScript

// input is an <input type="file"> element
const form = new FormData();
form.append("file", input.files[0]);
const response = await fetch("https://api.dharun.dev/v1/media/convert?format=wav&utm_medium=docs", { method: "POST", body: form });
if (!response.ok) throw new Error((await response.json()).error.message);
const file = await response.blob();

Python

import requests

files = [("file", open("speech.mp3", "rb"))]
response = requests.post("https://api.dharun.dev/v1/media/convert?format=wav&utm_medium=docs", files=files, timeout=90)
if not response.ok:
    raise RuntimeError(response.json()["error"]["message"])
open("speech.wav", "wb").write(response.content)
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Cut a clip

POST/v1/media/trim

Keeps the part from start to end. Options go in the query string, or as form fields when the file is sent as multipart/form-data.

Send: Audio or video ffmpeg can read (MP3, WAV, M4A, OGG, FLAC, MP4, MOV, WebM, MKV...), up to 10 MB; the first 10 minutes are used. Post the file as the request body, or as multipart/form-data. Try it with this sample.

The answer returns the audio itself; errors are JSON as everywhere else.

Model endpoint: it will need a free API key, sent as Authorization: Bearer <key> or X-API-Key. Until the date on API keys it answers without one and says so in the X-Key-Notice header. With a key: 500 model requests a day.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
startquerySeconds, or m:ss. Default 0.
endquery, requiredSeconds, or m:ss.
formatqueryOutput format when the file's own is not one of these. One of: mp3, wav, ogg, m4a, flac, mp4, webm, gif.

curl

# a sample to try: https://api.dharun.dev/samples/speech.mp3
curl -F "[email protected]" -o speech.mp3 "https://api.dharun.dev/v1/media/trim?start=0&end=1.5&utm_medium=docs"

JavaScript

// input is an <input type="file"> element
const form = new FormData();
form.append("file", input.files[0]);
const response = await fetch("https://api.dharun.dev/v1/media/trim?start=0&end=1.5&utm_medium=docs", { method: "POST", body: form });
if (!response.ok) throw new Error((await response.json()).error.message);
const file = await response.blob();

Python

import requests

files = [("file", open("speech.mp3", "rb"))]
response = requests.post("https://api.dharun.dev/v1/media/trim?start=0&end=1.5&utm_medium=docs", files=files, timeout=90)
if not response.ok:
    raise RuntimeError(response.json()["error"]["message"])
open("speech.mp3", "wb").write(response.content)
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Waveform picture

POST/v1/media/waveform

Send: Audio or video ffmpeg can read (MP3, WAV, M4A, OGG, FLAC, MP4, MOV, WebM, MKV...), up to 10 MB; the first 10 minutes are used. Post the file as the request body, or as multipart/form-data. Try it with this sample.

The answer returns the image itself; errors are JSON as everywhere else.

Model endpoint: it will need a free API key, sent as Authorization: Bearer <key> or X-API-Key. Until the date on API keys it answers without one and says so in the X-Key-Notice header. With a key: 500 model requests a day.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
widthquery100 to 4000. Default 1200.
heightquery40 to 1000. Default 200.
colorqueryHex. Default 2563eb.

curl

# a sample to try: https://api.dharun.dev/samples/speech.mp3
curl -F "[email protected]" -o out.png "https://api.dharun.dev/v1/media/waveform?width=800&height=160&utm_medium=docs"

JavaScript

// input is an <input type="file"> element
const form = new FormData();
form.append("file", input.files[0]);
const response = await fetch("https://api.dharun.dev/v1/media/waveform?width=800&height=160&utm_medium=docs", { method: "POST", body: form });
if (!response.ok) throw new Error((await response.json()).error.message);
const file = await response.blob();

Python

import requests

files = [("file", open("speech.mp3", "rb"))]
response = requests.post("https://api.dharun.dev/v1/media/waveform?width=800&height=160&utm_medium=docs", files=files, timeout=90)
if not response.ok:
    raise RuntimeError(response.json()["error"]["message"])
open("out.png", "wb").write(response.content)
Try it here

Change the values and send the request from your browser. Needs JavaScript.

A frame from a video

POST/v1/media/thumbnail

Send: Audio or video ffmpeg can read (MP3, WAV, M4A, OGG, FLAC, MP4, MOV, WebM, MKV...), up to 10 MB; the first 10 minutes are used. Post the file as the request body, or as multipart/form-data. Try it with this sample.

The answer returns the image itself; errors are JSON as everywhere else.

Model endpoint: it will need a free API key, sent as Authorization: Bearer <key> or X-API-Key. Until the date on API keys it answers without one and says so in the X-Key-Notice header. With a key: 500 model requests a day.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
atqueryTime, seconds or m:ss. Default 1.
widthquery32 to 3840. Default 640.

curl

# a sample to try: https://api.dharun.dev/samples/clip.mp4
curl -F "[email protected]" -o out.png "https://api.dharun.dev/v1/media/thumbnail?at=1&utm_medium=docs"

JavaScript

// input is an <input type="file"> element
const form = new FormData();
form.append("file", input.files[0]);
const response = await fetch("https://api.dharun.dev/v1/media/thumbnail?at=1&utm_medium=docs", { method: "POST", body: form });
if (!response.ok) throw new Error((await response.json()).error.message);
const file = await response.blob();

Python

import requests

files = [("file", open("clip.mp4", "rb"))]
response = requests.post("https://api.dharun.dev/v1/media/thumbnail?at=1&utm_medium=docs", files=files, timeout=90)
if not response.ok:
    raise RuntimeError(response.json()["error"]["message"])
open("out.png", "wb").write(response.content)
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Using an AI assistant? Connect the MCP server and it can call this API by itself. Want every endpoint on one bench? Open the playground.