Beatoven AI 自动生成音乐

Beatoven AI 自动生成音乐

一、源代码

import asyncio
import os
import aiohttp
import aiofiles
import argparse  # 导入 argparse 模块用于解析命令行参数

BACKEND_V1_API_URL = "https://public-api.beatoven.ai/api/v1"
BACKEND_API_HEADER_KEY = "xxx"  # 嵌入提供的 API 密钥

# 检查 API 密钥是否有效
if not BACKEND_API_HEADER_KEY:
    raise ValueError("BACKEND_API_HEADER_KEY is not set")


async def compose_track(request_data, session):
    try:
        async with session.post(
                f"{BACKEND_V1_API_URL}/tracks/compose",
                json=request_data,
                headers={"Authorization": f"Bearer {BACKEND_API_HEADER_KEY}"},
                timeout=30
        ) as response:
            data = await response.json()
            if response.status != 200 or not data.get("task_id"):
                raise Exception({"error": f"Composition failed: {data}"})
            return data
    except aiohttp.ClientConnectionError as e:
        raise Exception({"error": f"Could not connect to beatoven.ai: {str(e)}"}) from e
    except aiohttp.ClientError as e:
        raise Exception({"error": f"HTTP error: {str(e)}"}) from e
    except Exception as e:
        raise Exception({"error": f"Unexpected error: {str(e)}"}) from e


async def get_track_status(task_id, session):
    try:
        async with session.get(
                f"{BACKEND_V1_API_URL}/tasks/{task_id}",
                headers={"Authorization": f"Bearer {BACKEND_API_HEADER_KEY}"},
                timeout=30
        ) as response:
            if response.status == 200:
                data = await response.json()
                return data
            else:
                raise Exception({"error": f"Composition failed: {await response.text()}"})
    except aiohttp.ClientConnectionError as e:
        raise Exception({"error": f"Could not connect: {str(e)}"}) from e
    except aiohttp.ClientError as e:
        raise Exception({"error": f"HTTP error: {str(e)}"}) from e
    except Exception as e:
        raise Exception({"error": f"Unexpected error: {str(e)}"}) from e


async def handle_track_file(track_path: str, track_url: str, session):
    try:
        async with session.get(track_url, timeout=60) as response:
            if response.status == 200:
                async with aiofiles.open(track_path, "wb") as f:
                    await f.write(await response.read())
                return {}
            else:
                raise Exception({"error": f"Download failed: {await response.text()}"})
    except aiohttp.ClientConnectionError as e:
        raise Exception({"error": f"Could not download file: {str(e)}"}) from e
    except aiohttp.ClientError as e:
        raise Exception({"error": f"HTTP error: {str(e)}"}) from e
    except Exception as e:
        raise Exception({"error": f"Unexpected error: {str(e)}"}) from e


async def watch_task_status(task_id, session, interval=10):
    while True:
        track_status = await get_track_status(task_id, session)
        if "error" in track_status:
            raise Exception(track_status)

        print(f"Task status: {track_status}")
        if track_status.get("status") == "composing":
            await asyncio.sleep(interval)
        elif track_status.get("status") == "failed":
            raise Exception({"error": "Task failed"})
        else:
            return track_status


async def create_and_compose(text_prompt: str, session, duration: int = 180, audio_format: str = "mp3"):
    track_meta = {
        "prompt": {"text": text_prompt},
        "format": audio_format,
        "duration": duration  # 添加时长参数
    }
    try:
        compose_res = await compose_track(track_meta, session)
        task_id = compose_res["task_id"]
        print(f"Started composition task with ID: {task_id}")

        generation_meta = await watch_task_status(task_id, session)
        print(generation_meta)
        track_url = generation_meta["meta"]["track_url"]
        print("Downloading track file")
        await handle_track_file(
            os.path.join(os.getcwd(), f"composed_track_3.{audio_format}"), track_url, session
        )
        print(f"Composed! You can find your track as `composed_track_3.{audio_format}`")
    except Exception as e:
        print(f"Error: {str(e)}")
        raise


async def main():
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='生成AI音乐')
    parser.add_argument('--prompt', type=str, default="我需要一个环境、平静和冥想的轨道,带有柔软的合成器垫和慢速的瑜伽",
                        help='音乐描述文本')
    parser.add_argument('--duration', type=int, default=180,
                        help='音乐时长(秒)')
    parser.add_argument('--format', type=str, default="mp3",
                        choices=["mp3", "wav", "ogg"],
                        help='音频格式')
    args = parser.parse_args()

    # 使用上下文管理器来确保会话正确关闭
    async with aiohttp.ClientSession() as session:
        await create_and_compose(
            args.prompt, session, args.duration, args.format
        )


if __name__ == "__main__":
    # 使用 asyncio.run() 替代手动创建和管理事件循环
    # 这个函数会自动创建新的事件循环,运行任务,然后正确关闭事件循环
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("程序被用户中断")
    except Exception as e:
        print(f"发生错误: {e}")

此脚本通过调用 Beatoven AI 的接口,根据你的提示语(prompt)生成符合需求的背景音乐,并将其下载保存到本地。支持设置音乐时长、输出格式等参数。

PS:根据 Beatoven AI 分别做了两份JSON文件,可供Promot生成的AI进行参考以给出更符合 Beatoven AI 规范的promot


二、准备工作

1. 安装 Python 环境

确保你已经安装了 Python 3.7 及以上版本。可在终端输入以下命令检查:

python --version

如果未安装,请访问 https://www.python.org/ 下载安装。

2. 安装依赖库

进入脚本所在目录,执行以下命令安装所需的第三方依赖:

pip install aiohttp aiofiles

三、配置 API 密钥

在脚本中已经内嵌了一条 API 密钥:
申请网页:https://sync.beatoven.ai/workspace

BACKEND_API_HEADER_KEY = "xxx"

⚠️ 建议你替换为你自己的密钥,以防止密钥失效或滥用。


四、运行脚本

脚本支持命令行参数,你可以灵活指定以下选项:

  • --prompt: 音乐描述(提示语)
  • --duration: 音乐时长(单位:秒,默认 180)
  • --format: 音频格式(mp3 / wav / ogg)

示例一:使用默认参数

python beatoven_music_gen.py

等同于执行:

python beatoven_music_gen.py --prompt "我需要一个环境、平静和冥想的轨道,带有柔软的合成器垫和慢速的瑜伽" --duration 180 --format mp3

示例二:生成一段电影预告片风格音乐(30秒)

python beatoven_music_gen.py --prompt "史诗、紧张的电影配乐,包含弦乐和打击乐,快速节奏" --duration 30 --format wav

五、生成结果

生成完成后,音乐文件将被保存在当前工作目录中,文件名形如:

composed_track_3.mp3

控制台会输出如下内容:

Started composition task with ID: xxxxxxxx
Task status: composing
...
Task status: success
Downloading track file
Composed! You can find your track as `composed_track_3.mp3`

六、注意事项

  • 生成时间较长:通常在 10~60 秒不等,取决于时长与复杂度。

  • 提示词要尽量符合规范:参考 Beatoven 官方推荐结构(如:风格、情绪、节奏、使用场景等)。

  • 不支持歌词、人声指令:但可包含人声氛围元素。

  • 最大时长限制:音乐最大为 15 分钟(900 秒),最短为 10 秒。

  • 可能会有如下警告,但是不会影响音频生成

  •   Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000015DA57DF9D0>
      Traceback (most recent call last):
        File "D:\anaconda3\envs\Daily\lib\asyncio\proactor_events.py", line 116, in __del__
          self.close()
        File "D:\anaconda3\envs\Daily\lib\asyncio\proactor_events.py", line 108, in close
          self._loop.call_soon(self._call_connection_lost, None)
        File "D:\anaconda3\envs\Daily\lib\asyncio\base_events.py", line 719, in call_soon
          self._check_closed()
        File "D:\anaconda3\envs\Daily\lib\asyncio\base_events.py", line 508, in _check_closed
          raise RuntimeError('Event loop is closed')
      RuntimeError: Event loop is closed
      Traceback (most recent call last):
        File "D:\anaconda3\envs\Daily\lib\asyncio\proactor_events.py", line 116, in __del__
          self.close()
        File "D:\anaconda3\envs\Daily\lib\asyncio\proactor_events.py", line 108, in close
          self._loop.call_soon(self._call_connection_lost, None)
        File "D:\anaconda3\envs\Daily\lib\asyncio\base_events.py", line 719, in call_soon
          self._check_closed()
        File "D:\anaconda3\envs\Daily\lib\asyncio\base_events.py", line 508, in _check_closed
          raise RuntimeError('Event loop is closed')
      RuntimeError: Event loop is closed
    

七、示例提示词(Prompt)推荐

用途示例
YouTube vlog快乐、轻快,使用原声吉他和打击乐,中速节奏,适合晨间Vlog
游戏原声电子风格,紧张氛围,快速节奏,适合战斗场景
冥想音乐氛围风格、平静情绪,包含合成器音色,慢速节奏

prompt_guidelines.json

{
  "fields": [
    {
      "name": "genre",
      "description": "Specify the music style, e.g., Ambient, Cinematic, Lo-fi, Electronic, Rock, Jazz, Hip-hop."
    },
    {
      "name": "instruments",
      "description": "List the instruments or sounds to include, e.g., Piano, Guitar, Drums, Synth Pads, Electronic FX."
    },
    {
      "name": "mood",
      "description": "Describe the emotion you want, e.g., Calm, Energetic, Melancholic, Tense, Uplifting."
    },
    {
      "name": "tempo",
      "description": "Use descriptive terms rather than exact BPM, e.g., Slow, Medium, Fast."
    },
    {
      "name": "use_case",
      "description": "Explain the intended use, e.g., Podcast Background, Film Score, Game OST, YouTube Video."
    },
    {
      "name": "duration",
      "description": "Specify length, e.g., 30 seconds, 1 minute, 2 minutes; default is 1 minute."
    }
  ],
  "limitations": [
    "No transitions or crossfades",
    "No foley or sound effects",
    "No vocals",
    "Avoid technical music terms (scales, chords, exact BPM)"
  ],
  "suggestions": [
    "Keep prompts concise and clear",
    "Avoid jargon to improve generation accuracy",
    "Use simple adjectives for mood and tempo"
  ],
  "example": {
    "genre": "Ambient",
    "instruments": ["Soft Synth Pads"],
    "mood": "Calm",
    "tempo": "Slow",
    "use_case": "Yoga Session",
    "duration": "2 minutes"
  }
}

promot_guidelines_more.json

{
  "prompt": {
    "genre": {
      "description": "Specify the genre of music you want to create.",
      "type": "string",
      "examples": [
        "Ambient",
        "Cinematic",
        "Lo-fi",
        "Electronic",
        "Rock",
        "Jazz",
        "Hip-hop"
      ]
    },
    "instruments": {
      "description": "Mention the instruments you'd like featured (traditional or electronic).",
      "type": "array",
      "items": {
        "type": "string",
        "examples": [
          "piano",
          "guitar",
          "drums",
          "synthesizer",
          "pads"
        ]
      }
    },
    "mood": {
      "description": "Describe the mood or emotion you want the music to convey.",
      "type": "string",
      "examples": [
        "Happy",
        "Sad",
        "Tense",
        "Calm",
        "Uplifting",
        "Dark"
      ]
    },
    "tempo": {
      "description": "Choose a descriptive tempo rather than specific BPM values.",
      "type": "string",
      "enum": [
        "Slow",
        "Medium",
        "Fast",
        "Upbeat",
        "Chill",
        "Laidback"
      ],
      "notes": "Avoid numeric BPM to prevent misinterpretation."
    },
    "use_case": {
      "description": "Specify the intended use of the music.",
      "type": "string",
      "examples": [
        "Podcast background",
        "Film score",
        "Game soundtrack",
        "YouTube video"
      ]
    },
    "duration": {
      "description": "Desired track length in seconds or minutes.",
      "type": "string",
      "pattern": "^\\d+\\s?(s|seconds|m|minutes)$",
      "default": "1m",
      "constraints": {
        "min": "10s",
        "max": "15m",
        "optimum_range": "15s–2.5m"
      }
    }
  },
  "limitations": {
    "instruments": {
      "notes": "Some rare/specific instruments may not be available. You can download stems for individual tracks."
    },
    "transitions": {
      "supported": false,
      "notes": "Smooth transitions not currently supported."
    },
    "sound_effects_foley": {
      "supported": false,
      "notes": "Cannot generate sound effects or foley."
    },
    "vocals": {
      "supported": "instrumental layers only",
      "notes": "No lyrics or voiceover generation."
    },
    "loops": {
      "guaranteed": false,
      "notes": "Some output may loop, but not guaranteed."
    },
    "key_scales_time_signatures": {
      "supported": false,
      "notes": "Avoid specifying musical theory terms like ‘F#’, ‘minor’, ‘6/8’, etc."
    }
  },
  "examples": [
    {
      "prompt": "Ambient, calm, meditative track with soft synth pads, slow tempo, for a yoga session.",
      "duration": "1m"
    },
    {
      "prompt": "Cinematic, epic orchestral piece, fast tempo, heroic mood, 30s, for a movie trailer."
    },
    {
      "prompt": "Lo-fi, chill track with jazzy guitar, relaxed tempo, nostalgic mood, 2m, for a study playlist."
    },
    {
      "prompt": "Happy, upbeat music with acoustic guitar and light percussion, medium tempo, 1.5m, for a morning vlog."
    }
  ]
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ac157ol

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值