一、Suno API简介
Suno是一家提供AI音乐生成服务的平台,其API允许开发者将先进的音乐生成能力集成到自己的应用中。通过简单的API调用,用户可以根据文本提示生成独特的音乐作品。
主要功能特点:
- 根据文本描述生成音乐
- 支持多种音乐风格
- 可定制音乐长度和结构
- 提供高质量的音频输出
二、项目准备
1. 获取API密钥
首先,你需要在AceData平台注册开发者账号并获取API密钥。这个密钥将用于验证你的API请求。AceDatahttps://share.acedata.cloud/r/1uKk7FP2fw
注册帐号后登录平台,点击所有“服务”找到Ai音频如下图所示:
然后点击suno 音乐生成模块:
申请接口后购买积分,用于音乐生成与测试
2.购买好后进入控制台的申请列表中找到suno音乐生成并查询key密钥:
3.配置接口
headers: {
"accept": "application/json",
"authorization": "Bearer b8e6b2303fc64d0c9780634d2fxxxxx",
//替换成你的密钥
"content-type": "application/json"
},
三、运行效果
四、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ai音乐生成_fruitstudio</title>
<style>
body {
font-family: 'Arial', sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
}
.container {
background-color: white;
padding: 25px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #2c3e50;
}
input, textarea, select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
box-sizing: border-box;
transition: border 0.3s;
}
input:focus, textarea:focus, select:focus {
border-color: #3498db;
outline: none;
}
textarea {
height: 120px;
resize: vertical;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 14px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
width: 100%;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
button:disabled {
background-color: #95a5a6;
cursor: not-allowed;
}
.result {
margin-top: 30px;
display: none;
}
.loading {
text-align: center;
margin: 30px 0;
display: none;
}
.spinner {
border: 5px solid rgba(0, 0, 0, 0.1);
width: 50px;
height: 50px;
border-radius: 50%;
border-left-color: #3498db;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.song-card {
background-color: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.song-header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.song-image {
width: 100px;
height: 100px;
border-radius: 6px;
object-fit: cover;
margin-right: 15px;
}
.song-title {
font-size: 20px;
font-weight: bold;
margin: 0;
}
.song-meta {
color: #7f8c8d;
font-size: 14px;
margin-top: 5px;
}
.audio-player {
width: 100%;
margin: 15px 0;
}
.lyrics {
background-color: #f0f3f4;
padding: 15px;
border-radius: 6px;
white-space: pre-line;
font-family: 'Courier New', monospace;
line-height: 1.6;
}
.download-btn {
display: inline-block;
padding: 8px 15px;
background-color: #2ecc71;
color: white;
text-decoration: none;
border-radius: 4px;
margin-top: 10px;
font-size: 14px;
}
.error {
color: #e74c3c;
margin-top: 15px;
padding: 10px;
background-color: #fdecea;
border-radius: 4px;
display: none;
}
.success {
color: #27ae60;
margin-top: 15px;
padding: 10px;
background-color: #e8f5e9;
border-radius: 4px;
display: none;
}
.versions {
margin-top: 20px;
border-top: 1px solid #eee;
padding-top: 20px;
}
.version-title {
font-weight: bold;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Ai音乐生成</h1>
<div class="form-group">
<label for="prompt">歌曲描述</label>
<textarea id="prompt" placeholder="e.g. 'A happy pop song about summer love' "></textarea>
</div>
<div class="form-group">
<label for="model">模型选择</label>
<select id="model">
<option value="chirp-v3-0" selected>Chirp v3.0</option>
<option value="chirp-v2-0">Chirp v2.0</option>
</select>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="instrumental"> 伴奏
</label>
</div>
<button id="generate-btn">点击生成</button>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>音乐生成中......请耐心等待</p>
</div>
<div class="error" id="error"></div>
<div class="success" id="success"></div>
<div class="result" id="result">
<!-- Results will be inserted here -->
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const generateBtn = document.getElementById('generate-btn');
generateBtn.addEventListener('click', generateMusic);
});
async function generateMusic() {
const prompt = document.getElementById('prompt').value.trim();
const model = document.getElementById('model').value;
const instrumental = document.getElementById('instrumental').checked;
if (!prompt) {
showError('Please enter a song description');
return;
}
// Show loading state
document.getElementById('loading').style.display = 'block';
document.getElementById('generate-btn').disabled = true;
document.getElementById('result').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('success').style.display = 'none';
try {
const options = {
method: "POST",
headers: {
"accept": "application/json",
"authorization": "Bearer b8e6b2303fc64d0c9780634dxxxxxxxx", // Replace with your actual API key
"content-type": "application/json"
},
body: JSON.stringify({
"action": "generate",
"prompt": prompt,
"model": model,
"custom": false,
"instrumental": instrumental
})
};
const response = await fetch("https://api.acedata.cloud/suno/audios", options);
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const data = await response.json();
if (!data.success) {
throw new Error(data.message || 'Failed to generate music');
}
// Show success message
showSuccess('Music generated successfully!');
// Display the results
displayResults(data);
} catch (error) {
showError('Error generating music: ' + error.message);
console.error('Generation error:', error);
} finally {
document.getElementById('loading').style.display = 'none';
document.getElementById('generate-btn').disabled = false;
}
}
function displayResults(data) {
const resultContainer = document.getElementById('result');
resultContainer.innerHTML = '';
if (!data.data || data.data.length === 0) {
showError('No songs were generated');
return;
}
// Group songs by title (since API returns multiple versions)
const songsByTitle = {};
data.data.forEach(song => {
if (!songsByTitle[song.title]) {
songsByTitle[song.title] = [];
}
songsByTitle[song.title].push(song);
});
// Create a card for each song title
for (const [title, versions] of Object.entries(songsByTitle)) {
const primaryVersion = versions[0];
const songCard = document.createElement('div');
songCard.className = 'song-card';
// Song header with image and title
songCard.innerHTML = `
<div class="song-header">
<img src="${primaryVersion.image_url}" alt="${title}" class="song-image">
<div>
<h3 class="song-title">${title}</h3>
<div class="song-meta">
<div>Model: ${primaryVersion.model}</div>
<div>Style: ${primaryVersion.style}</div>
<div>Duration: ${Math.round(primaryVersion.duration)} seconds</div>
</div>
</div>
</div>
<div class="versions">
<div class="version-title">Versions (${versions.length})</div>
</div>
`;
// Add each version
const versionsContainer = songCard.querySelector('.versions');
versions.forEach((song, index) => {
const versionElement = document.createElement('div');
versionElement.className = 'song-version';
versionElement.innerHTML = `
<div style="margin-bottom: 15px;">
<div style="font-weight: bold; margin-bottom: 5px;">Version ${index + 1}</div>
<audio controls class="audio-player">
<source src="${song.audio_url}" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<a href="${song.audio_url}" download="${title.replace(/[^a-z0-9]/gi, '_')}_v${index + 1}.mp3" class="download-btn">
Download MP3
</a>
</div>
<details style="margin-top: 10px;">
<summary>Show Lyrics</summary>
<div class="lyrics">${song.lyric}</div>
</details>
`;
versionsContainer.appendChild(versionElement);
});
resultContainer.appendChild(songCard);
}
document.getElementById('result').style.display = 'block';
}
function showError(message) {
const errorElement = document.getElementById('error');
errorElement.textContent = message;
errorElement.style.display = 'block';
}
function showSuccess(message) {
const successElement = document.getElementById('success');
successElement.textContent = message;
successElement.style.display = 'block';
}
</script>
</body>
</html>