Introduction
Base url
https://api.cleanvoice.ai/v2
https://api.cleanvoice.ai/v2
https://api.cleanvoice.ai/v2
https://api.cleanvoice.ai/v2
Welcome to the Cleanvoice API 👋
With this API you can automatically submit files to be edited by Cleanvoice, access existing edits and export them to various formats.
This is a REST API that uses predictable resource names and verbs. Our API is versioned where breaking changes are released as incremental versions. We'll try our best not to release versions too often, and to reasonably support legacy versions.
Try our API Playground:
https://app.cleanvoice.ai/playground/
Click here if you want access to the swagger docs
If you have any questions, please write to us at support@cleanvoice.ai. We'd love to hear from you!
— Cleanvoice team
Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "https://api.cleanvoice.ai/v2/account" \
-H "X-API-Key: **your_api_key_here**"
import requests
url = 'https://api.cleanvoice.ai/v2/account'
headers = {'X-API-Key': '**your_api_key_here**'}
requests.get(url, headers=headers)
require 'net/http'
require 'uri'
uri = URI.parse('https://api.cleanvoice.ai/v2/account')
header = { 'X-API-Key': '**your_api_key_here**' }
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri, header)
response = http.request(request)
import axios from 'axios';
const url = 'https://api.cleanvoice.ai/v2/account';
const headers = {'X-API-Key': '**your_api_key_here**'};
axios.get(url, { headers })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
Make sure to replace
**your_api_key_here**
with your API key.
Cleanvoice uses API keys to allow access to the API. You can get your API key by logging in and going to settings
Cleanvoice expects the API key to be included in all API requests to the server in a header that looks like the following:
X-Api-Key: **your_api_key_here**
Uploads
To get started, you have to provide a video or audio file.
There are two ways to upload your audio files(s):
- a public media file URL (accesible to our servers)
- direct file upload via the API.
Option 1: Upload via Public URL
You can directly use publicly available URLs to upload media files to Cleanvoice. This can be a publicly accessible URL hosted by yourselves or a third-party. The files will be automatically downloaded from the URL, so you don't need to explicitly upload them. For example, you can use a URL like "https://yourdomain.com/file.mp3". If you choose to use this option, you can proceed directly to the Edit Section
Option 2: Upload via File
If you choose the option to upload files, you will need to explicitly upload them to Cleanvoice servers. The files will be stored in our R2 European Cloudflare bucket.
After uploading, the API will return a link which you will need for starting a new edit. To upload files to our R2 Cloudflare bucket, you will first need to request a signed URL by using the provided endpoints.
Step 1 - Get a Signed Url
curl -X 'POST' \
'https://api.cleanvoice.ai/v2/upload?filename=audio.mp3' \
-H 'X-API-Key: **your_api_key_here**'
import requests
url = 'https://api.cleanvoice.ai/v2/upload?filename=audio.mp3'
headers = {'X-API-Key': '**your_api_key_here**'}
response = requests.post(url, headers=headers)
signed_url = response.json()['signedUrl']
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse('https://api.cleanvoice.ai/v2/upload?filename=audio.mp3')
header = { 'X-API-Key': '**your_api_key_here**' }
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri, header)
response = http.request(request)
signed_url = JSON.parse(response.body)["signedUrl"]
import axios from 'axios';
const url = 'https://api.cleanvoice.ai/v2/upload?filename=audio.mp3';
const headers = {'X-API-Key': '**your_api_key_here**'};
const response = await axios.post(url, {headers});
const signed_url = response.data.signedUrl;
The above command returns JSON structured like this:
{
"signedUrl": "https://f9c8803feb33484a51d0df72dc0fb4a6.eu.r2.cloudflarestorage.com/uploads/uploads/myfile.mp3?response-content-disp..."
}
This endpoint returns a signed URL which can be used to make PUT requests to our bucket.
Once the file is uploaded, this same url should be used as the files
URL when creating the associated edit.
HTTP Request
POST https://api.cleanvoice.ai/v2/upload
Parameters
Parameter | Description |
---|---|
filename | (required) The filename and extension of the media file (e.g. my_media.mp3 ) |
2. Upload your file with the Signed Url
curl -X PUT -T my_media.mp3 -L "https://signed-url..."
import requests
url = "https://signed-url..."
file = open("my_media.mp3", "rb")
requests.put(url, data=file)
import axios from 'axios';
const url = "https://signed-url...";
const file = new File(["my_media.mp3"], "my_media.mp3", {
type: "audio/mp3"
});
axios.put(url, file)
.then(response => {
console.log(response.status);
})
.catch(error => {
console.log(error);
});
require 'uri'
require 'net/http'
signed_url = "https://signed-url..."
uri = URI(signed_url)
req = Net::HTTP::Put.new(uri)
req.body = File.read("my_media.mp3")
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
Simple upload to an S3 Bucket
Once you have a signed url, you have to upload the file there, and you do it as you would with any S3 bucket.
To upload a file to the signed URL you may use cURL like the example on the right.
Note: You can upload, but not download the file with this url. The purpose is to upload the file for us to edit it.
Edits
Create a Edit
curl -X POST "https://api.cleanvoice.ai/v2/edits" \
-H "X-API-Key: **your_api_key_here**" \
-H "Content-Type: application/json" \
-d '{
"input": {
"files": [
"https://public.com/file.mp3"
],
"config": {}
}
}'
import requests
import json
file_url = "https://public.com/file.mp3_OR_Signed_URL"
api_key = "**your_api_key_here**"
data = {
"input": {
"files": [file_url],
"config": {}
}
}
headers = {
"X-API-Key": api_key,
"Content-Type": "application/json"
}
response = requests.post("https://api.cleanvoice.ai/v2/edits", json=data, headers=headers)
print(response.json())
import axios from 'axios';
const fileUrl = "https://public.com/file.mp3_OR_Signed_URL";
const apiKey = "**your_api_key_here**";
const data = {
input: {
files: [fileUrl],
config: {}
}
};
const headers = {
"X-API-Key": apiKey,
"Content-Type": "application/json"
};
axios.post("https://api.cleanvoice.ai/v2/edits", data, { headers })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
require 'net/http'
require 'json'
file_url = "https://public.com/file.mp3_OR_Signed_URL"
api_key = "**your_api_key_here**"
data = {
input: {
files: [file_url],
config: {}
}
}.to_json
headers = {
"X-API-Key" => api_key,
"Content-Type" => "application/json"
}
uri = URI("https://api.cleanvoice.ai/v2/edits")
response = Net::HTTP.post(uri, data, headers)
puts JSON.parse(response.body)
The above command returns JSON structured like this:
{
"id": "9a14b8fe-3604-43e4-8c06-06a7491ae8fc"
}
This endpoint creates a new edit. After a edit is created, the system will proceed to automatically editing it. You can check if the editing process has finished by retrieving a edit.
We strongly checking out the API Playground to see all the possible configurations and how they affect the audio. https://app.cleanvoice.ai/playground/
Cleanvoice requires a public link to edit your audio, if this is not possible go back to the upload section. If you have already uploaded your audio via our api, you can use the signed URL instead.
Note all uploads and edits are stored for 7 days only. If you require longer storage, write us.
The API can edit multi-track audio as well. Multi-track uploads are where every audio file contains a different speaker. To use it, just pass multiple files. Single-Track are where all the speakers are merged into a single file.
HTTP Request
POST https://api.cleanvoice.ai/v2/edits
Parameters
Input
Parameter | Type | Description |
---|---|---|
files | Array | (required) A list of URL-Strings containing Audio. For Single-Track, a single link is located in the array. Else Cleanvoice assumes it's a multi-track audio recording |
Config
Parameter | Type | Description |
---|---|---|
video | Boolean | If true, indicates that the input is a video file. This will process the audio track of the video. Default: False. |
send_email | Boolean | Send an email to your account with the edited file(s). Default: False. |
long_silences | Boolean | Identify and remove long silences. Default: False. |
stutters | Boolean | Identify and remove stutters. Default: False. |
fillers | Boolean | Identify and remove filler sounds. Default: False. |
mouth_sounds | Boolean | Identify and remove mouth sounds. Default: False. |
hesitations | Boolean | Identify and remove hesitations. Default: False. |
muted | Boolean | Mute specified segments instead of cutting them. Relevant if mute_lufs is set. Default: False. |
remove_noise | Boolean | Remove background noise. Can also avoid removing music if keep_music is true, making edits less aggressive in sections with music. Default: True. |
keep_music | Boolean | Avoids removing or editing sections with music to preserve the musical background. Default: False. |
breath | Boolean | Reduce the loudness of breath sounds, making them less noticeable while maintaining a natural sound. Can be controlled further by setting mute_lufs . Default: False. |
normalize | Boolean | Normalize audio levels. If true, target_lufs is by default -16 LUFS. Advised to be true if merge is used. Default: False. |
autoeq (Legacy) | Boolean | Apply automatic EQ adjustments. Sound Studio will replace it. Default: False. |
sound_studio | Boolean | An AI-powered sound studio enhancer. Default: False. |
mute_lufs | Integer | Specifies the loudness level (in LUFS) below which segments are muted or breath sounds are reduced. Default is -80, must be a negative integer, max 0. |
target_lufs | Integer | Target loudness level (in LUFS) for the audio. Needs to be less than 0. Default: -16 if normalize is true. |
export_format | String | The format to export the edited audio in. Supports "auto", "mp3", "wav", "flac", "m4a". Default: "auto". |
transcription | Boolean | Transcribe the audio to text. Default: False. |
summarize | Boolean | Provide a summary of the audio content. Requires transcription to be true. Default: False. |
social_content | Boolean | Indicates the need for content to be optimized for social media sharing. Requires summarize to be true. Default: False. |
export_timestamps | Boolean | Export timestamps of edits. Default: False. |
signed_url | String | A user-provided S3 link where the results are uploaded via a PUT request. Default: Null (if not used). |
merge | Boolean | Mix multi-track files into one. Recommended to use with normalize=true for best results. Default: False. |
Retrieve a Edit
curl "https://api.cleanvoice.ai/v2/edits/<ID>" \
-H "X-Api-Key: **your_api_key_here**"
import requests
url = "https://api.cleanvoice.ai/v2/edits/<ID>"
headers = {
"X-Api-Key": "**your_api_key_here**"
}
response = requests.get(url, headers=headers)
print(response.json())
import axios from 'axios';
const url = "https://api.cleanvoice.ai/v2/edits/<ID>";
const headers = {
"X-Api-Key": "**your_api_key_here**"
};
axios.get(url, { headers })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
require 'net/http'
require 'json'
url = "https://api.cleanvoice.ai/v2/edits/<ID>"
headers = {
"X-Api-Key" => "**your_api_key_here**"
}
uri = URI(url)
response = Net::HTTP.get_response(uri, headers)
puts JSON.parse(response.body)
The above command returns JSON structured like this:
{
"status": "SUCCESS",
"result": {
"video": false,
"filename": "98d88d834dca4d61a1cadd1d42d9fcd4",
"statistics": {
"BREATH": 340,
"DEADAIR": 124,
"STUTTERING": 2,
"MOUTH_SOUND": 5,
"FILLER_SOUND": 17
},
"download_url": "https://fra1.digitaloceanspaces.com/cleanvoice/uploads/b309cb56-0ae7-4...",
"summarization": {
"title": "Combating Poaching with AI: Protecting Endangered Wildlife",
"summary": "In this episode of the Weird AI...",
"chapters": [
{
"start": 0,
"title": "AI Combats Poaching to Save Elephants"
},
{
"start": 230.65,
"title": "Tracking Wildlife with Motion-Activated Cameras"
},...
],
"summaries": [
"In this episode ...",
"The speakers discuss..",
...
],
"key_learnings": "...",
"summary_of_summary": "...",
"episode_description": "..."
},
"transcription": {
"paragraphs": [
{
"end": 5.84,
"text": " This episode has been recorded two weeks before the war in Ukraine last year.",
"start": 0
},
ing which deals with probability a lot",
"start": 667.2
},..
],
"transcription": {
"words": [
{
"id": 0,
"end": 0.365,
"text": "This",
"start": 0
},
{
"id": 1,
"end": 1.00375,
"text": "episode",
"start": 0.365
},.. ],
"paragraphs": [
{
"id": 0,
"end": 9.872665534804755,
"start": 0.7385398981324278,
"speaker": "SPEAKER_01"
},..
]
}
},
"social_content": [..,
"merged_audio_url": [...],
"timestamps_markers_urls": [...]
},
"task_id": "b309cb56-0ae7-477d-8fcc-15052bb297e4"
}
This endpoint retrieves information about a specific edit. The results can be used in two ways.
- Retrieve the edited audio by downloading the download_url
- Edit your audio yourself and use the edits as references.
HTTP Request
GET https://api.cleanvoice.ai/v2/edits/<ID>
Edits State Descriptions
Value | Description |
---|---|
PENDING |
Waiting for execution or unknown edit ID |
STARTED |
Edit has been started |
SUCCESS |
Audio has been successfully edited |
RETRY |
Task is being retried |
FAILURE |
File failed to process |
Delete Files
We delete all uploads (raw files & edited files) 7 days after being processed. However if you want to delete them sooner, you can send a delete request.
curl -X 'DELETE' \
'https://api.cleanvoice.ai/v2/edits/<job_id>' \
-H 'X-API-Key: **your_api_key_here**'
import requests
url = 'https://api.cleanvoice.ai/v2/edits/<job_id>'
headers = {'X-API-Key': '**your_api_key_here**'}
response = requests.delete(url, headers=headers)
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse('https://api.cleanvoice.ai/edits/<job_id>')
header = { 'X-API-Key': '**your_api_key_here**' }
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Delete.new(uri.request_uri, header)
response = http.request(request)
import axios from 'axios';
const url = 'https://api.cleanvoice.ai/edits/<job_id>';
const headers = {'X-API-Key': '**your_api_key_here**'};
const response = await axios.delete(url, {headers});
Languages
We support the following languages:
Code | Language | Support |
---|---|---|
EN |
English | Full |
DE |
German | Full |
RO |
Romanian | Full |
FR |
French | Partial |
NL |
Dutch | Partial |
BG |
Bulgarian (Bulgaria) | Partial |
AR |
Arabic (United Arab Emirates) | Partial |
tr-TR |
Turkish (Turkey) | Partial |
PL |
Polish | Partial |
IT |
Italian | Partial |
ES |
Spanish | Partial |
PT |
Portuguese | Partial |
Note that, we don't work on the word level. We work on the phonetical level, therefore if theres a language which is similar to two languages which we have listed, it could work as well. Say German and English are supported, then Dutch should work as well.