五分钟搭建一个Suno AI音乐站点

news2024/12/31 7:30:38

五分钟搭建一个Suno AI音乐站点

在这个数字化时代,人工智能技术正以惊人的速度改变着我们的生活方式和创造方式。音乐作为一种最直接、最感性的艺术形式,自然也成为了人工智能技术的应用场景之一。今天,我们将以Vue和Node.js为基础,利用现有的API来快速搭建一个Suno AI音乐站点。让我们一起探索这个令人兴奋的过程吧!

一、准备工作

在动手之前,我们需要确保已经准备好了必要的环境和工具:

Vue和Node.js环境:确保你的开发环境中已经配置好了Vue和Node.js,这将是我们构建前端和后端的基础。

文本编辑器或IDE:选择你熟悉和喜欢的文本编辑器,如VS Code、Sublime Text等。

Suno AI音乐API密钥:这是我们生成音乐所需的关键。这里我们选择的是Acedata提供的Suno API,注册方法如下:

我们先到 Suno Audios Generation API 页面申请Suno API 服务:

如果你尚未登录或注册,会跳转到登录页面邀请您来注册和登录,注册登录之后会自动返回当前页面。

在首次申请时会有免费额度赠送,可以免费使用该 API。申请了API后,在 Credentials 查找到 Token,点击复制这个值备用,类似这样的:8125d23343388839c6e

好了,现在,我们获得了Suno API,下面就可以来快速的搭建AI音乐生成平台了。

二、搭建前端和后端

1. 创建Vue项目

为了更清晰地组织前端和后端代码,我们将项目目录结构分为两个主要部分:frontend和backend。以下是具体的目录结构和说明:

目录结构
suno-music-site/
│
├── backend/
│   ├── node_modules/
│   ├── package.json
│   ├── package-lock.json
│   └── server.js
│
├── frontend/
│   ├── node_modules/
│   ├── public/
│   ├── src/
│   │   ├── assets/
│   │   ├── components/
│   │   ├── App.vue
│   │   ├── main.js
│   ├── package.json
│   ├── package-lock.json
│   └── vue.config.js
│
└── README.md

我们创建一个 suno-music-site 目录。

2. 创建后端

创建后端目录和文件,在项目根目录下创建 backend 目录,并进入该目录:

mkdir backend
cd backend

初始化Node.js项目

在backend目录下初始化Node.js项目:

npm init -y

安装Express和其他依赖
安装Express和所需的依赖包:

npm install express body-parser node-fetch

创建server.js
在backend目录下创建server.js文件,并添加以下代码:

const express = require('express');
const bodyParser = require('body-parser');
const fetch = require('node-fetch').default; // 使用CommonJS版本的node-fetch
const cors = require('cors'); // 引入cors中间件

const app = express();
const PORT = 3000;

app.use(cors()); // 使用cors中间件
app.use(bodyParser.json());

app.post('/generate-music', async (req, res) => {
  const { prompt } = req.body;
  const options = {
    method: "post",
    headers: {
      "accept": "application/json",
      "authorization": "Bearer 6675520380424c0167881d69c6e",
      "content-type": "application/json"
    },
    body: JSON.stringify({
      "prompt": prompt
    })
  };

  try {
    const response = await fetch("https://api.acedata.cloud/suno/audios", options);
    const data = await response.json();        
    res.json(data);

  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'An error occurred' });
  }
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
3. 创建前端

回到项目根目录,创建frontend目录,并进入该目录:

cd ..
mkdir frontend
cd frontend

创建Vue项目
使用Vue CLI创建Vue项目:

vue create .

选择默认配置或根据你的需要进行配置。

编写前端代码
我们创建一个简单的界面来接收用户输入并显示生成的音乐。

在frontend/src目录下,修改App.vue文件,添加以下代码:

<template>
  <div id="app">
    <header>
      <h1>XiaoZhi AI Music Generator</h1>
    </header>
    <main>
      <div class="input-container">
        <input type="text" v-model="musicTitle" placeholder="Enter a prompt for the music">
        <button @click="handleGenerateMusic" :disabled="loading">生成音乐</button>
      </div>
      
      <div v-if="loading" class="loading">
        Music is being generated for you, please wait...
      </div>

      <div v-if="musicGenerated" class="music-container">
        <div v-for="music in generatedMusic" :key="music.id" class="music-item">
          <h2>{{ music.title }}</h2>
          <img :src="music.image_url" alt="Music Image">
          <p class="lyric">{{ music.lyric }}</p>
          <audio controls class="audio" @play="stopOtherMedia($event)">
            <source :src="music.audio_url" type="audio/mpeg">
            Your browser does not support the audio element.
          </audio>
          <video controls class="video" @play="stopOtherMedia($event)">
            <source :src="music.video_url" type="video/mp4">
            Your browser does not support the video element.
          </video>
        </div>
      </div>

      <div v-if="showModal" class="modal">
        <div class="modal-content">
          <p>{{ modalMessage }}</p>
        </div>
      </div>
    </main>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      musicTitle: '',
      musicGenerated: false,
      generatedMusic: [],
      loading: false,
      currentPlayingMedia: null,
      showModal: false,
      modalMessage: ''
    };
  },
  mounted() {
    document.title = "XiaoZhi AI Music Generator";
  },
  methods: {
    handleGenerateMusic() {
      if (!this.musicTitle) {
        this.showModalMessage('请输入生成音乐的提示语');
        return;
      }
      this.generateMusic();
    },
    generateMusic() {
      this.loading = true;
      this.musicGenerated = false;
      axios.post('http://localhost:3000/generate-music', { prompt: this.musicTitle })
        .then(response => {
          this.loading = false;
          this.musicGenerated = true;
          this.generatedMusic = response.data.data;
        })
        .catch(error => {
          this.loading = false;
          console.error('Error generating music:', error);
        });
    },
    stopOtherMedia(event) {
      if (this.currentPlayingMedia && this.currentPlayingMedia !== event.target) {
        this.currentPlayingMedia.pause();
        this.currentPlayingMedia.currentTime = 0;
      }
      this.currentPlayingMedia = event.target;
    },
    showModalMessage(message) {
      this.modalMessage = message;
      this.showModal = true;
      setTimeout(() => {
        this.showModal = false;
      }, 2000);
    }
  }
}
</script>

<style scoped>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

header {
  background-color: #42b983;
  padding: 20px;
  color: white;
}

main {
  margin: 20px;
  max-width: 80%;
  margin: 20px auto;
}

.input-container {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  margin-bottom: 20px;
}

input[type="text"] {
  padding: 7px;
  margin-right: 10px;
  font-size: 1em;
  flex: 1;
  max-width: 600px;
}

button {
  padding: 8px 20px;
  background-color: #007bff;
  color: #fff;
  border: none;
  cursor: pointer;
  font-size: 1em;
  border-radius: 4px;
}

button:disabled {
  background-color: #d3d3d3;
  cursor: not-allowed;
}

button:hover:not(:disabled) {
  background-color: #0056b3;
}

.loading {
  font-size: 1.2em;
  color: #42b983;
  margin-top: 20px;
}

.music-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.music-item {
  flex: 1;
  min-width: 300px;
  max-width: 45%;
  margin-top: 20px;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
  background-color: #f9f9f9;
  text-align: left;
}

.lyric {
  font-size: 1.2em;
  margin: 10px 0;
  white-space: pre-line;
}

.audio {
  width: 100%;
  margin-top: 10px;
}

.video {
  width: 100%;
  height: auto;
  margin-top: 10px;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
  text-align: center;
  font-size: 1.2em;
}

@media (max-width: 600px) {
  .input-container {
    flex-direction: column;
  }
  
  input[type="text"] {
    margin-right: 0;
    margin-bottom: 10px;
    max-width: 100%;     
    
  }

  .music-item {
    max-width: 100%;
  }
}

@media (min-width: 601px) {
  .video {
    width: 100%;
    margin: 10px auto;
  }
}
</style>
4. 解决跨域问题

在你的项目运行中,可能会出现跨域请求的问题,我们需要解决它。
你可以在现有的 vue.config.js 文件中添加开发服务器代理配置,以解决跨域问题。以下是修改后的 vue.config.js 文件内容:

const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    proxy: {
      '/generate-music': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  }
})

这样配置后,当前端发起请求到/generate-music时,代理服务器会将请求转发到运行在 http://localhost:3000 的后端服务,从而解决跨域问题。

如果还无法解决的话,你可能还需要处理一下。由于浏览器安全策略的限制,前端和后端运行在不同的域(例如,localhost 和 192.168.0.235)时,浏览器会阻止跨域请求。我们需要在后端服务器中设置适当的CORS头信息来允许跨域请求。

你可以使用 cors 中间件来解决这个问题。

安装 cors 包:

npm install cors

在 server.js 文件中引入并使用 cors 中间件:

这样,后端服务器将允许来自所有来源的请求。如果你想限制特定来源的请求,可以这样配置 cors 中间件:

app.use(cors({
  origin: 'http://192.168.20.235:8081' // 允许的前端URL
}));

这样应该能解决CORS问题,并允许前端正常调用后端API。

如果Node.js 无法直接使用 ES 模块(ES Module)加载 node-fetch,因 node-fetch 是一个 ES 模块。解决这个问题的一种方法是将 node-fetch 替换为一个可以在 CommonJS 环境中使用的版本。

你可以安装 node-fetch 的 CommonJS 版本,并修改 server.js 文件中的引入方式。
首先,删除项目中已安装的 node-fetch:

npm uninstall node-fetch

安装 node-fetch 的 CommonJS 版本:

npm install node-fetch@2

在 server.js 文件中,将引入方式修改为动态引入(dynamic import),上面的代码已经修改好了。

三. 运行项目

  1. 启动后端服务

在backend目录下,启动后端服务:

node server.js
  1. 启动前端服务
    在frontend目录下,启动前端服务:
npm run serve

打开浏览器,访问http://localhost:8080(Vue CLI默认端口),你将看到一个简单的界面,输入一个提示词并点击“Generate Music”按钮,即可生成音乐。

默认会生成两首音乐,有 MP3 和 MP4 视频,点击即可播放 AI 生成的音乐。

点击以下音频或视频链接试听:

您的浏览器不支持 audio 元素。

播放/暂停

您的浏览器不支持 video 元素。

播放/暂停

https://cdn1.suno.ai/ab8dcd9b-3527-46da-b0c7-4d1a78b51846.mp3

https://cdn1.suno.ai/3cbd5b7b-7354-48a3-8158-9cd87e1b116b.mp4

MP3试听

MP4试看

四、结语

通过这种方式,我们成功地将前端和后端代码分离,清晰地组织在不同的目录下,同时也实现了跨域请求。希望这个项目能给你带来启发,并帮助你更好地理解和实现类似的项目。

这样我们就搭建好了一个本地的AI音乐生成平台,如果你愿意,可以将代码打包后上传到服务器,再绑定一个域名,就可以提供给其他小伙伴一起来使用了。

通过Vue和Node.js,以及Acedata提供的Suno AI音乐API的强大功能,我们在短短的时间内成功搭建了一个AI音乐生成网站。这个过程不仅展示了人工智能技术在音乐创作中的威力,也向我们展示了如何利用现有的技术来创造出令人惊叹的新体验。希望这个项目能够激发你的创造灵感,并让你更加深入地探索人工智能与音乐的奇妙结合!

在线体验站点:

http://suno.morecale.com莫卡乐AI音乐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1697880.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第12章-ADC采集电压和显示 基于STM32的ADC—电压采集(详细讲解+HAL库)

我们的智能小车用到了ADC测量电池电压的功能&#xff0c;这章节我们做一下。 我们的一篇在这里 第一篇 什么是ADC 百度百科介绍&#xff1a; 我们知道万用表 电压表可以测量电池&#xff0c;或者电路电压。那么我们是否可以通过单片机获得电压&#xff0c;方便我 们监控电池状…

WPF学习日常篇(一)--开发界面视图布局

接下来开始日常篇&#xff0c;我在主线篇&#xff08;正文&#xff09;中说过要介绍一下我的界面排布&#xff0c;科学的排布才更科学更有效率的进行敲代码和开发。日常篇中主要记录我的一些小想法和所考虑的一些细节。 一、主界面设置 主界面分为左右两部分&#xff0c;分为…

查分数组总结

文章目录 查分数组定义应用举例LeetCode 1109 题「[航班预订统计] 查分数组定义 差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。 通过这个 diff 差分数组是可以反推出原始数组 nums 的&#xff0c;代码逻辑如下&#xff1a; int res[diff.size()]; // 根…

(2024,SDE,对抗薛定谔桥匹配,离散时间迭代马尔可夫拟合,去噪扩散 GAN)

Adversarial Schrdinger Bridge Matching 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 4. 实验 0. 摘要 薛定谔桥&#xff08;Schrdinger Bridge&#xff0c;SB&…

flash-linear-attention中的Chunkwise并行算法的理解

这里提一下&#xff0c;我维护的几三个记录个人学习笔记以及社区中其它大佬们的优秀博客链接的仓库都获得了不少star&#xff0c;感谢读者们的认可&#xff0c;我也会继续在开源社区多做贡献。github主页&#xff1a;https://github.com/BBuf &#xff0c;欢迎来踩 0x0. 前言 …

MySQL——索引与事务

目录 前言 一、索引 1.索引概述 &#xff08;1&#xff09;基本概念 &#xff08;2&#xff09;索引作用 &#xff08;3&#xff09;索引特点 &#xff08;4&#xff09;适用场景 2.索引的操作 &#xff08;1&#xff09;查看索引 &#xff08;2&#xff09;创建索引…

【算法题】520 钻石争霸赛 2024 全解析

都是自己写的代码&#xff0c;发现自己的问题是做题速度还是不够快 520-1 爱之恒久远 在 520 这个特殊的日子里&#xff0c;请你直接在屏幕上输出&#xff1a;Forever and always。 输入格式&#xff1a; 本题没有输入。 输出格式&#xff1a; 在一行中输出 Forever and always…

2024年推荐的适合电脑和手机操作的线上兼职副业平台

总是会有人在找寻着线上兼职副业&#xff0c;那么在如今的2024年&#xff0c;互联网提供了诸多方便&#xff0c;无论你是宝妈、大学生、程序员、外卖小哥还是打工族&#xff0c;如果你正在寻找副业机会&#xff0c;那么这篇文章将为你提供一些适合电脑和手机操作的线上兼职副业…

[Linux]文件/文件描述符fd

一、关于文件 文件&#xff1d;内容&#xff0b;属性 那么所有对文件的操作&#xff0c;就是对内容/属性操作。内容是数据&#xff0c;属性也是数据&#xff0c;那么存储文件&#xff0c;就必须既存储内容数据&#xff0c;又存储属性数据。默认就是在磁盘中的文件。当进程访问…

知识分享:隔多久查询一次网贷大数据信用报告比较好?

随着互联网金融的快速发展&#xff0c;越来越多的人开始接触和使用网络贷款。而在这个过程中&#xff0c;网贷大数据信用报告成为了评估借款人信用状况的重要依据。那么&#xff0c;隔多久查询一次网贷大数据信用报告比较好呢?接下来随小易大数据平台小编去看看吧。 首先&…

YOLOV5 改进:替换backbone为EfficientNet

1、介绍 本章将会把yolov5的主干网络替换成EfficientNet V2,这里直接粘贴代码 详细的可以参考之前的内容:YOLOV5 改进:替换backbone(MobileNet为例)_yolov5主干网络更换为mobile-CSDN博客 更多的backbone更换参考本专栏: YOLOV5 实战项目(训练、部署、改进等等)_听风吹…

2024电工杯B题平衡膳食食谱的优化设计及评价原创论文分享

大家好&#xff0c;从昨天肝到现在&#xff0c;终于完成了2024电工杯数学建模B题的完整论文啦。 实在精力有限&#xff0c;具体的讲解大家可以去讲解视频&#xff1a; 给大家看一下目录吧&#xff1a; 目录 摘 要&#xff1a; 10 一、问题重述 14 二&#xff0e;问题分析 …

2024.05.26 第 399 场周赛

Leetcode 第 399 场周赛 优质数对的总数 I Leetcode 优质数对的总数 I 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#xff08;0 < i < n…

航运复兴?大摩不信!

大摩认为&#xff0c;从供需关系来看红海危机只是推迟了航运业下行周期的到来&#xff0c;一旦干扰消除&#xff0c;行业可能重回周期性低迷。 红海危机加剧运力紧张&#xff0c;航运市场价格飞涨。 大摩在24日的一份报告中指出&#xff0c;受红海危机干扰航运市场运力&#…

加密与安全_AES RSA 密钥对生成及PEM格式的代码实现

文章目录 RSA&#xff08;非对称&#xff09;和AES&#xff08;对称&#xff09;加密算法一、RSA&#xff08;Rivest-Shamir-Adleman&#xff09;二、AES&#xff08;Advanced Encryption Standard&#xff09; RSA加密三种填充模式一、RSA填充模式二、常见的RSA填充模式组合三…

Python小游戏——俄罗斯方块

文章目录 项目介绍环境配置代码设计思路1.初始化和导入库&#xff1a;2.定义颜色和屏幕尺寸&#xff1a;3.定义游戏逻辑&#xff1a;4.游戏循环&#xff1a; 源代码效果图 项目介绍 俄罗斯方块游戏是一款经典的益智游戏&#xff0c;玩家通过旋转和移动各种形状的方块&#xff…

页面<html>上多了一个滚动条,定位发现是<body>里面多了一个id为trans-tooltip的div

现象分析&#xff1a; 页面根标签html多了一个滚动条&#xff0c;发现body里面多了一个id为trans-tooltip的div&#xff0c;虽然width为0&#xff0c;height为0&#xff0c;但是其子元素还是有高度&#xff0c;占据了空间&#xff0c;最终导致了滚动条&#xff1b; 根本原因&…

怎么在pyqt中显示matplotlib的绘图?

想要在pyqt中显示matplotlib的绘图&#xff0c;在绘图时&#xff0c;其实不必使用以下语句&#xff1a; matplotlib.use("Qt5Agg") # 声明使用QT5最关键的语句是&#xff1a; from matplotlib.backends.backend_qt5agg import FigureCanvasQTAggFigureCanvasQTAgg…

Selenium 自动化测试工具<2>(Selenium 常用API的使用方法)

文章目录 浏览器操作浏览器最大化设置浏览器的大小浏览器的前进和后退操作浏览器滚动条 键盘事件单个按键用法键盘组合键用法 鼠标事件不同窗口搜索定位一组元素定位多层框架下拉框定位alert、confirm、prompt 的处理上传文件操作自动截屏 继上一篇文章对 Selenium API 的使用&…