You need to enable JavaScript to run this app.
导航

接口说明

最近更新时间2023.08.03 19:52:35

首次发布时间2021.08.23 16:15:12

接入必读

请先查看接入必读了解具体接入方式,再参考此文档完成接入。

功能介绍

MusicTagging 为用户提供音乐标签分类能力,通过曲风、情绪、场景、语言、二级曲风5个维度分析音乐,自动生成各维度下的分类标签以及对应概率值。

  • 输入:一段音乐音频,以及音乐标签任务参数
  • 输出:指定标签类别的预测概率值

接口说明

  • 当前支持通过 HTTP 协议在线调用

  • 请求内容包括:

    • payload字段为将请求参数序列化后的json文本
    • data字段为将音频二进制文件按照base64格式编码(标准base64,RFC 4648)的文本
  • 使用备注:

注意项说明

功能

限制说明

  • 不支持非音乐类音频
  • 避免直接拼接json文本,尽量使用转换库,避免造成转义符等导致json格式错误
输入音频格式支持wav、pcm、mp3、aac等常见格式
音频编码建议采样率大于等于16kHz,否则将进行自动转码,可能带来效果损失和更多耗时处理
音频时长限制小于等于10分钟;建议大于5s,否则会影响算法效果
音频大小限制小于等于100MB
输出结果格式详情请参考响应格式

公共参数

参考详细说明功能调用-通用协议

配置参数

payload配置参数为json字符串格式

字段描述类型是否必传默认值
url服务请求数据的url,若data字段为空,则使用该url下载音频数据。详见功能调用-通用协议-payload.urlstring-
audio_info音频参数,便于服务节省音频解码耗时object-
audio_info.format音频编码格式,wav/mp3/aacstring-
audio_info.sample_rate音频采样率number-
audio_info.channel音频通道数number-
extra补充参数object-
extra.enable_tag是否返回标签信息booltrue
extra.enable_embed是否返回embedding信息boolfalse
extra.top_num设置每个分组返回的最大标签数量,默认全部返回number1

响应格式

HTTP响应Content-Type: application/json

字段描述类型
task_id请求任务id,用于链路追踪、问题排查string
namespace服务接口命名空间,比如MusicTaggingstring
data请求响应二进制数据,标准base64编码string
payload请求响应文本信息,json字符串格式string
status_code状态码number
status_text状态信息string
  • 响应结果payload为json字符串格式,json内容格式如下:
字段描述类型
pred标签预测概率值,取值范围:[0, 1.0]array
embedoptional,标签维度embedding,可用于其他模型输入array
task_flow任务流响应结果object
task_flow.result子任务响应结果数组array
task_flow.result.task_type子任务类型string
task_flow.result.pred_dim子任务响应结果中预测概率值的维度number
task_flow.result.embed_dim子任务响应结果中embedding的维度number
task_flow.result.task_output子任务响应结果的其他附加信息object
task_flow.result.task_output.tags子任务响应结果的标签附加信息array

payload示例:

{
  "pred": [0.09001981,0.05727265,...,0.14518361],
  "task_flow": {
    "result": [
      {
        "task_type": "MusicTaggingMood",
        "pred_dim": 6,
        "task_output": {
          "tags": [
            "sorrow",
            "chill",
            "excited",
            "happy",
            "angry",
            "romantic"
          ]
        }
      },
      {
        "task_type": "MusicTaggingTheme",
        "pred_dim": 14,
        "task_output": {
          "tags": [
            "kadian",
            "DIY",
            "family",
            "sound_effect",
            "campus",
            "ACG",
            "game",
            "pet",
            "Beauty_fashion",
            "travel",
            "Chinese_Style",
            "cool",
            "dancale",
            "vlog"
          ]
        }
      }
    ]
  }
}

参考示例

调用方式为:POST /api/v1/invoke

Golang

// Code sample:
// use http client to invoke SAMI HTTP Service
package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

type InvokeResponse struct {
	StatusCode int32   `form:"status_code,required" json:"status_code,required" query:"status_code,required"`
	StatusText string  `form:"status_text,required" json:"status_text,required" query:"status_text,required"`
	TaskId     string  `form:"task_id,required" json:"task_id,required" query:"task_id,required"`
	Namespace  string  `form:"namespace,required" json:"namespace,required" query:"namespace,required"`
	Payload    *string `form:"payload,omitempty" json:"payload,omitempty" query:"payload,omitempty"`
	Data       []byte  `form:"data,omitempty" json:"data,omitempty" query:"data,omitempty"`
	State      *string `form:"state,omitempty" json:"state,omitempty" query:"state,omitempty"`
}

const (
	domain = "https://sami.bytedance.com"

	// auth token
	appkey    = "your_appkey"

	// SAMI method
	version   = "v4"
	namespace = "MusicTagging"

	// dump output
	dataOutputFile    = "output.wav"
	payloadOutputFile = "output.json"
	isDump            = true
)

func main() {
	// Get token
	token := "your_token"

	// Construct HTTP request
	//   1. Read local audio file
	//   2. Set HTTP json body
	//   3. Do HTTP POST request
	audioPath := "/path/to/audio"
	content, err := ioutil.ReadFile(audioPath)
	if err != nil {
		log.Fatalf("failed to read file: %v", err)
	}
	data := base64.StdEncoding.EncodeToString(content)
	body := fmt.Sprintf(
		`{"data": "%v", "payload":"{\"task_flow\":{\"type\":\"merge\",\"task\":`+
			`[{\"task_type\":\"MusicTaggingGenre17\"},{\"task_type\":\"MusicTaggingMood10\"},`+
			`{\"task_type\":\"MusicTaggingTheme24\"},{\"task_type\":\"MusicTaggingLang24\"},`+
			`{\"task_type\":\"MusicTaggingVocal\"},{\"task_type\":\"MusicTaggingMTT\"}]},`+
			`\"extra\":{\"use_tag\":false}}"}`, data,
	)
	urlPath := fmt.Sprintf(
		"%v/api/v1/invoke?version=%v&token=%v&appkey=%v&namespace=%v",
		domain, version, token, appkey, namespace,
	)
	log.Printf("invoke request: %v", urlPath)

	// HTTP POST request
	start := time.Now()
	resp, err := http.Post(urlPath, "application/json", bytes.NewBuffer([]byte(body)))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	// Parse HTTP response
	ret, err := ioutil.ReadAll(resp.Body)
	if err != nil || resp.StatusCode != http.StatusOK {
		panic(string(ret))
	}
	log.Printf("http invoke: cost=%vms, response: %v", time.Since(start).Milliseconds(), string(ret))

	// parse SAMI response
	samiResp := InvokeResponse{}
	payloadStr := ""
	if err = json.Unmarshal(ret, &samiResp); err != nil {
		log.Println("parse response failed", string(ret), err)
		panic(err)
	}
	if samiResp.Payload != nil {
		payloadStr = *samiResp.Payload
	}
	log.Printf("response task_id=%v, payload=%v, data=[%d]byte", samiResp.TaskId, payloadStr, len(samiResp.Data))
	if isDump && samiResp.Payload != nil {
		_ = ioutil.WriteFile(payloadOutputFile, []byte(*samiResp.Payload), 0644)
	}
	if isDump && len(samiResp.Data) > 0 {
		_ = ioutil.WriteFile(dataOutputFile, samiResp.Data, 0644)
	}
}

Python

import base64
import json
import sys

import requests

# Construct HTTP request
payload = json.dumps({"task_flow": {"type": "merge",
                                    "task": [{"task_type": "MusicTaggingGenre17"}, {"task_type": "MusicTaggingMood10"},
                                             {"task_type": "MusicTaggingTheme24"}, {"task_type": "MusicTaggingLang24"},
                                             {"task_type": "MusicTaggingVocal"}, {"task_type": "MusicTaggingMTT"}]}})
with open("/path/to/audio", "rb") as f:
    data = f.read()
    data = base64.b64encode(data).decode('utf-8')
req = {
    "appkey": "your_appkey",
    "token": "your_token",
    "namespace": "MusicTagging",
    "payload": payload,
    "data": data
}

if __name__ == "__main__":
    # HTTP POST request
    resp = requests.post("https://sami.bytedance.com/api/v1/invoke", json=req)

    # Parse HTTP SAMI response
    try:
        sami_resp = resp.json()
        if resp.status_code != 200:
            print(sami_resp)
            sys.exit(1)
    except:
        print(resp)
        sys.exit(1)

    print("response task_id=%s status_code=%d status_text=%s" % (
        sami_resp["task_id"], sami_resp["status_code"], sami_resp["status_text"]), end=" ")
    if "payload" in sami_resp and len(sami_resp["payload"]) > 0:
        print("payload=%s" % sami_resp["payload"], end=" ")

常见问题

附录

音乐标签模型列表

  • MusicTaggingVocal,2类人声标签
  • MusicTaggingMood10,10类情绪标签
  • MusicTaggingGenre34,34类曲风标签
  • MusicTaggingTheme24,24类场景标签
  • MusicTaggingLang30,30类语种标签
标签模型维度标签字段标签含义
MusicTaggingVocal2vocal声乐
non_vocal纯音乐
MusicTaggingMood1010cute可爱
dynamic动感
tense紧张
weird诡异
sorrow悲伤
chill宁静
excited兴奋
happy喜悦
angry气愤
romantic浪漫
MusicTaggingGenre3434pop流行
rock摇滚
electronic电子音乐
hiphop_rap嘻哈
reggae雷鬼
mb_soul/
Metal金属
Jazz爵士
Blues布鲁斯
Country乡村
Folk民谣
Indie独立音乐
K_pop韩国流行
Indie_Pop独立流行
Muslim穆斯林音乐
Indo_Christian印度基督教音乐
Bollywood宝莱坞音乐
Bollywood_Retro宝莱坞音乐
Urban_Punjabi_Pop都市旁遮普流行
Tamil_Film_Music泰米尔电影音乐
Kannada_Film_Music卡纳达电影音乐
Telugu_Film_Music泰卢固电影音乐
Indian_Independent印度独立音乐
Malayalam_Film_Music马拉雅拉姆电影音乐
Sertanejo巴西乡村音乐
Baile_Funk舞蹈放克音乐
Gospel福音
Samba桑巴
Pagode巴西舞曲
MPB巴西全域音乐
Forro巴西Forró
Axe巴西Axé
Reggaeton说唱音乐和加勒比风格
Brazilian_Punk巴西朋克
MusicTaggingTheme2424kadian卡点
DIYDIY
family家庭
sound_effect音效
campus校园
ACG二次元
game游戏
pet宠物
Beauty_fashion美妆
travel旅行
Chinese_Style中国风
cool潮酷
disco_dance迪斯科
vlogVlog
dance舞蹈
djDJ
food美食
love爱情
rainy
sport运动
spring
summer
sunny阳光
funny搞笑
MusicTaggingLang3030en英文
es西班牙语
fr法语
pt葡萄牙语
it意大利语
de德语
cmn普通话
id印尼语
ja日语
hi印地语
paPunjabi (印度方言)
tlTagalog (他加禄语)
ru俄语
tr土耳其语
ms马来语
th泰语
ko韩语
pl波兰语
ar阿拉伯语
taTamil (泰米尔语)
teTelugu(泰卢固语)
mlMalayalam (马拉雅拉姆语)
knKannada (卡纳达语)
bnBengali (孟加拉语)
guGujarati (古吉拉特语)
mrMarathi(马拉地语)
bhoBhopal (博帕尔)
yue粤语
minnan闽南语
other其他