歌曲上架前最容易漏掉三件事:有没有商用权利、有没有 AI 标识、响度是否达标。这篇写一个检查清单脚本。它读入
tracks.csv(每首歌的原始文件、成品文件、创作时的订阅计划、下载时是否在订阅期内)和 A 篇生成的 C2PA 报告,自己测量成品的响度并读取标签,最后给出 OK、WARN 或 BLOCK,并写出release_report.csv。
先看清成品(box 上真实运行;C2PA 结果来自对 Suno 官方接口的真实调用)
- 3 首测试歌:1 首 WARN、2 首 BLOCK。
- 免费计划的歌被正确拦下。
- 没处理过的原文件同时触发了 4 条问题:响度、AI 标识、C2PA、订阅措辞。
- pytest 3 项通过。
合规提醒:截至本文写作时(2026-10),Suno 没有公开的、可自助开通的生成 API。网上流传的“Suno API”封装大多是通过模拟登录或抓取 cookie 调用内部接口,违反服务条款,还可能导致封号,本文一律不用。歌曲请在 Suno 官方网页或 App 里生成,本文只处理两件事:一是调用 Suno 官方公开的免费 C2PA 检测接口,二是对你下载的文件做本地后期处理。权利以 Suno 帮助中心为准:免费计划生成的歌只能个人非商用;在 Pro 或 Premier 订阅期间创作的歌可以商用。歌词和参考素材不得侵犯他人版权,也不要模仿真实歌手的声音冒充本人。在中国境内发布,要遵守《生成式人工智能服务管理暂行办法》,并按《人工智能生成合成内容标识办法》标注“AI 生成”。本文不列订阅价格。
运行说明:权利规则是我按 Suno 帮助中心 2026-10 的内容整理的,只能用于工程上的初筛,不构成法律意见。另外我注意到,2026-09-03 更新的那篇《付费订阅的权利》写的是“订阅期间下载的歌”有商用权,而其他文章写的是“订阅期间创作”。所以“创作时在订阅期内、下载时已经退订”这种情况,脚本标为 WARN,请向 Suno 确认。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
release_check.py |
检查权利、C2PA、响度和 AI 标识,给出分级 |
tracks.csv |
3 首示例歌 |
c2pa_report.csv |
用 A 篇脚本真实生成的检测结果 |
master.py、demo_*.mp3 |
从 B 篇复制过来(用于测量响度和读取标签) |
test_release.py |
测试 OK、免费计划、原始文件三种情况 |
需要准备哪些环境?
和 B 篇相同(ffmpeg、Python、pytest)。生成 C2PA 报告需要联网,用的是 A 篇的脚本。
文件结构
51-suno-C-src/
├── release_check.py
├── tracks.csv
├── c2pa_report.csv
├── master.py
├── demo_track.mp3
├── demo_master.mp3
└── test_release.py
第 1 步:代码
"""发布前检查清单:对每首歌检查商用权利、Suno 凭据、响度和 AI 标识,给出 OK / WARN / BLOCK。
权利规则来自 Suno 帮助中心(2026-10 查阅):
- 免费(Basic)计划生成的歌只能个人非商用,之后升级也不会自动追溯授权;
- 在 Pro / Premier 订阅期间创作的歌有商用权,退订后仍然保留;
- 2026-09-03 更新的那篇文章写的是“订阅期间下载的歌”有商用权,和其他文章的“订阅期间创作”措辞不同,
所以“创作时订阅了、下载时没订阅”的情况标 WARN,请以 Suno 条款或客服答复为准。
这只是工程上的初筛,不构成法律意见。"""
import csv, sys
from master import measure, tags
TARGET_I, TOL, MAX_TP = -14.0, 1.0, -1.0
def check(row, c2pa):
out = []
plan = row["plan_when_created"].strip().lower()
if plan in ("free", "basic"):
out.append(("BLOCK", "免费计划生成:仅限个人非商用,不能上架变现"))
elif plan in ("pro", "premier"):
if row.get("subscribed_when_downloaded", "yes").strip().lower() != "yes":
out.append(("WARN", "创作时有订阅、下载时没有:帮助中心不同文章措辞不一致,请向 Suno 确认"))
else:
out.append(("BLOCK", f"未知计划:{plan}"))
v = c2pa.get(row["original"])
if v is None:
out.append(("WARN", "原始文件还没做 C2PA 检测(运行 A 篇脚本)"))
elif v != "verified_suno":
out.append(("WARN", f"原始文件 C2PA 结果为 {v}:确认文件是不是 Suno 原始下载"))
m = measure(row["master"])
i, tp = float(m["input_i"]), float(m["input_tp"])
if abs(i - TARGET_I) > TOL or tp > MAX_TP:
out.append(("WARN", f"响度 {i} LUFS / 真峰值 {tp} dBTP,未达到 {TARGET_I}±{TOL} LUFS、≤{MAX_TP} dBTP"))
note = tags(row["master"]).get("comment", "")
if "ai" not in note.lower() and "人工智能" not in note:
out.append(("BLOCK", "成品缺少 AI 生成标识(comment 标签),发布时还要在平台上勾选或声明"))
level = "BLOCK" if any(l == "BLOCK" for l, _ in out) else "WARN" if out else "OK"
return level, out, i, tp
def main(tracks="tracks.csv", c2pa_csv="c2pa_report.csv", out="release_report.csv"):
c2pa = {}
try:
c2pa = {r["target"]: r["verdict"] for r in csv.DictReader(open(c2pa_csv, encoding="utf-8"))}
except FileNotFoundError:
pass
rows = list(csv.DictReader(open(tracks, encoding="utf-8")))
with open(out, "w", newline="", encoding="utf-8") as f:
w = csv.writer(f); w.writerow(["title", "level", "lufs", "true_peak", "reasons"])
for r in rows:
level, why, i, tp = check(r, c2pa)
w.writerow([r["title"], level, i, tp, ";".join(x for _, x in why)])
print(f"{level:<5} {r['title']}")
for l, x in why:
print(f" [{l}] {x}")
print("报告:", out)
if __name__ == "__main__":
main(*sys.argv[1:])
第 2 步:输入
title,original,master,plan_when_created,subscribed_when_downloaded
秋日夜市(Pro 期间创作),demo_track.mp3,demo_master.mp3,pro,yes
旧歌(免费计划),demo_track.mp3,demo_master.mp3,free,yes
未处理的原文件,demo_track.mp3,demo_track.mp3,premier,no
第 3 步:测试
from release_check import check
C = {"demo_track.mp3": "verified_suno"}
def test_ok_when_everything_fine():
level, why, *_ = check({"original": "demo_track.mp3", "master": "demo_master.mp3", "plan_when_created": "pro",
"subscribed_when_downloaded": "yes"}, C)
assert level == "OK", why
def test_free_plan_blocked():
level, why, *_ = check({"original": "demo_track.mp3", "master": "demo_master.mp3", "plan_when_created": "free"}, C)
assert level == "BLOCK"
def test_raw_file_has_no_label_and_loudness_off():
level, why, *_ = check({"original": "demo_track.mp3", "master": "demo_track.mp3", "plan_when_created": "premier",
"subscribed_when_downloaded": "no"}, C)
msgs = " ".join(x for _, x in why)
assert level == "BLOCK" and "响度" in msgs and "措辞" in msgs
第 4 步:运行
$ python ../51-suno-A-src/suno_c2pa.py demo_track.mp3 # 真实调用 Suno 检测接口
no_suno_provenance demo_track.mp3 No Suno content credentials found.
报告: c2pa_report.csv
$ python release_check.py
WARN 秋日夜市(Pro 期间创作)
[WARN] 原始文件 C2PA 结果为 no_suno_provenance:确认文件是不是 Suno 原始下载
BLOCK 旧歌(免费计划)
[BLOCK] 免费计划生成:仅限个人非商用,不能上架变现
[WARN] 原始文件 C2PA 结果为 no_suno_provenance:确认文件是不是 Suno 原始下载
BLOCK 未处理的原文件
[WARN] 创作时有订阅、下载时没有:帮助中心不同文章措辞不一致,请向 Suno 确认
[WARN] 原始文件 C2PA 结果为 no_suno_provenance:确认文件是不是 Suno 原始下载
[WARN] 响度 -10.18 LUFS / 真峰值 -1.18 dBTP,未达到 -14.0±1.0 LUFS、≤-1.0 dBTP
[BLOCK] 成品缺少 AI 生成标识(comment 标签),发布时还要在平台上勾选或声明
报告: release_report.csv
$ python -m pytest -q
3 passed in 0.92s
调试示例
第一首歌各项都合规,为什么还是 WARN? 它的成品响度达标、带有 AI 标签,创作时也在 Pro 订阅期内,唯一的问题是 C2PA 结果为 no_suno_provenance。原因是演示用的 demo_track.mp3 是 ffmpeg 合成的,本来就不是 Suno 生成的,所以真实接口如实回答“没有凭据”。
换成真正从 Suno 下载的原文件,应该会得到 verified_suno,这首歌就会变成 OK(这一点在单元测试 test_ok_when_everything_fine 里用假数据验证过)。这条 WARN 的意义在于:它能发现“拿错了文件”,比如误用了处理过的成品,或者混进了别处来的音频。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 免费计划的歌被 BLOCK | 官方规定免费计划只能非商用,升级后也不追溯 | 在订阅期内重新创作,或只做非商用用途 |
| 所有歌都提示“还没做 C2PA 检测” | original 列的路径和报告里的 target 不一致 |
两边用同样写法的路径 |
| 响度 WARN | 成品没有经过 B 篇处理 | 先运行 master.py |
| AI 标识 BLOCK | comment 标签里没有 AI 字样 | 用 B 篇写入标签,并在发布平台上主动声明 |
模板规则
- 权利判断以官方帮助中心为准,措辞不一致的地方标 WARN,不擅自下结论。
- 原始文件和成品分别检查:原文件看 C2PA,成品看响度和标签。
- 只要有一项 BLOCK,就不能发布。
项目资源
| 用途 | 地址 |
|---|---|
| Suno 内容凭据与检测接口说明 | https://suno.com/suno-credentials |
| Suno 帮助:Suno 是否拥有我的音乐 | https://help.suno.com/en/articles/2416769 |
| Suno 帮助:免费计划的权利 | https://help.suno.com/en/articles/9601601 |
| Suno 帮助:付费订阅的权利 | https://help.suno.com/en/articles/9601665 |
| Suno 帮助:能否发布到 Spotify 等平台 | https://help.suno.com/en/articles/2410177 |
| Suno 帮助:订阅后能否追溯之前的歌 | https://help.suno.com/en/articles/2425729 |
把这份报告和原文件一起存档,以后遇到平台审核或版权问题,可以拿出来证明当时检查过。