You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行音乐生成Python脚本遇TypeError,寻求修复方案

音乐生成器TypeError错误修复方案

报错信息

1 frames
<ipython-input-7-3be77148eaa3> in create_training_data(data)
     39     # 遍历数据并提取相关信息
     40     for i in range(len(data['energy'])):
---&gt; 41         X[i][0] = data['energy'][i]
     42         X[i][1] = data['chroma_stft'][i]
     43         X[i][2] = data['spectral_contrast'][i]

TypeError: 'numpy.float64' object does not support item assignment

错误原因分析

  1. 数组维度不匹配:create_training_data中X = np.zeros(data_shape[0])创建的是一维数组,但代码中使用了X[i][0]这种二维索引赋值,直接触发类型错误。
  2. Librosa特征维度处理错误:Librosa提取的音频特征(如energy、chroma_stft)均为二维数组(形状为(特征维度, 时间步数量)),直接按索引取值会导致维度混乱。
  3. 循环范围错误:len(data['energy'])获取的是特征维度数(比如energy的形状是(1, n),长度为1),而非实际需要遍历的时间步数量。
  4. 隐藏问题:原代码中file_retreival函数未返回sample_rate,但main函数尝试调用data['sample_rate'];create_music中拍号处理逻辑错误,无法直接将"4/4"格式传入time_signature消息。

修正方案

1. 修复file_retreival函数

添加采样率返回,并统一特征维度为时间步优先:

def file_retreival(file): 
    audio, sample_rate = librosa.load(file)
    
    results = {
        "sample_rate": sample_rate,  # 新增返回采样率
        "tempo": librosa.beat.tempo(audio, sample_rate)[0],  # 提取tempo标量值
        "energy": librosa.feature.rms(audio)[0],  # 转换为一维数组(时间步维度)
        "chroma_stft": librosa.feature.chroma_stft(audio).T,  # 转置为(时间步, 12)的二维数组
        "spectral_contrast": librosa.feature.spectral_contrast(audio).T,  # 转置为(时间步, 7)的二维数组
        "tonnetz": librosa.feature.tonnetz(y=librosa.effects.harmonic(audio)).T  # 转置为(时间步, 6)的二维数组
    }
    return results

2. 重构create_training_data函数

创建正确维度的训练数组,按时间步拼接所有特征:

def create_training_data(data):
    # 获取时间步数量(所有特征的时间步一致)
    time_steps = len(data['energy'])
    # 计算总特征数:1(energy) +12(chroma)+7(contrast)+6(tonnetz)+1(tempo) =27
    feature_num = 1 + data['chroma_stft'].shape[1] + data['spectral_contrast'].shape[1] + data['tonnetz'].shape[1] +1
    # 创建二维训练数组:(时间步数量, 总特征数)
    X = np.zeros((time_steps, feature_num))
    
    for i in range(time_steps): 
        X[i][0] = data['energy'][i]
        X[i][1:13] = data['chroma_stft'][i]  # 填充12维chroma特征
        X[i][13:20] = data['spectral_contrast'][i]  # 填充7维频谱对比度特征
        X[i][20:26] = data['tonnetz'][i]  # 填充6维tonnetz特征
        X[i][26] = data['tempo']  # 填充tempo标量
    return X 

3. 修复create_music中的拍号处理

拆分用户输入的"4/4"格式,适配mido的参数要求:

def create_music(pred, sample_rate, tempo, rhythm, tone):
    from mido import Message, MidiFile
    from mido.midifiles import MidiTrack
    
    mid = MidiFile()
    track = MidiTrack() 
    mid.tracks.append(track)
    
    # 将BPM转换为mido所需的微秒每拍
    mido_tempo = mido.bpm2tempo(tempo)
    track.append(Message("set_tempo", tempo=mido_tempo))
    
    # 拆分拍号输入(如"4/4"转为分子4、分母4)
    numerator, denominator = map(int, rhythm.split('/'))
    track.append(Message("time_signature", numerator=numerator, denominator=denominator))
    
    # 遍历预测结果生成音符
    for note_val, duration in pred:
        track.append(Message("note_on", note=int(note_val), velocity=127, time=0)) 
        track.append(Message("note_off", note=int(note_val), velocity=127, time=int(duration*1000))) 
    
    # 用控制消息设置基调示例
    track.append(Message("control_change", control=0, value=2))
    mid.save("generated_music.mid")

4. 修正main函数中的标签维度

确保标签数组与训练数据行数匹配:

def main():
    file = "audio.mp3"
    data = file_retreival(file)
    X_train = create_training_data(data)
    # 标签维度与训练数据行数一致
    y_train = np.zeros(X_train.shape[0])
    model = build_model(X_train, y_train)
    music_pred = generate_music(model, X_train)
    create_music(music_pred, data['sample_rate'], tempo, rhythm, tone)

完整修正代码

# 导入必要的库 
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import librosa
import mido

# 获取用户输入
tempo = int(input("你希望歌曲的速度是多少?(BPM)"))
rhythm = input("你希望歌曲的节奏是怎样的?(例如4/4)")
tone = input("歌曲的‘感觉’或基调是什么?(例如欢快、忧郁)")

# 文件读取函数
def file_retreival(file): 
    audio, sample_rate = librosa.load(file)
    
    results = {
        "sample_rate": sample_rate,
        "tempo": librosa.beat.tempo(audio, sample_rate)[0],
        "energy": librosa.feature.rms(audio)[0],
        "chroma_stft": librosa.feature.chroma_stft(audio).T,
        "spectral_contrast": librosa.feature.spectral_contrast(audio).T,
        "tonnetz": librosa.feature.tonnetz(y=librosa.effects.harmonic(audio)).T
    }
    return results

# 创建训练数据函数
def create_training_data(data):
    time_steps = len(data['energy'])
    feature_num = 1 + data['chroma_stft'].shape[1] + data['spectral_contrast'].shape[1] + data['tonnetz'].shape[1] +1
    X = np.zeros((time_steps, feature_num))
    
    for i in range(time_steps): 
        X[i][0] = data['energy'][i]
        X[i][1:13] = data['chroma_stft'][i]
        X[i][13:20] = data['spectral_contrast'][i]
        X[i][20:26] = data['tonnetz'][i]
        X[i][26] = data['tempo']
    return X 

# 构建模型函数
def build_model(X_train, y_train):
    from sklearn.ensemble import RandomForestClassifier
    model = RandomForestClassifier(n_estimators=100)
    model.fit(X_train, y_train) 
    return model 

# 生成音乐函数(示例:输出音符和时长)
def generate_music(model, X):
    # 示例:生成60-80范围的音符,0.5-2秒的时长
    pred_notes = np.random.randint(60,80, size=X.shape[0])
    pred_durations = np.random.uniform(0.5,2, size=X.shape[0])
    return np.column_stack((pred_notes, pred_durations))

# 创建音乐文件函数
def create_music(pred, sample_rate, tempo, rhythm, tone):
    mid = MidiFile()
    track = MidiTrack() 
    mid.tracks.append(track)
    
    mido_tempo = mido.bpm2tempo(tempo)
    track.append(Message("set_tempo", tempo=mido_tempo))
    
    numerator, denominator = map(int, rhythm.split('/'))
    track.append(Message("time_signature", numerator=numerator, denominator=denominator))
    
    for note_val, duration in pred:
        track.append(Message("note_on", note=int(note_val), velocity=127, time=0)) 
        track.append(Message("note_off", note=int(note_val), velocity=127, time=int(duration*1000))) 
    
    track.append(Message("control_change", control=0, value=2))
    mid.save("generated_music.mid")

# 主函数 
def main():
    file = "audio.mp3"
    data = file_retreival(file)
    X_train = create_training_data(data)
    y_train = np.zeros(X_train.shape[0])
    model = build_model(X_train, y_train)
    music_pred = generate_music(model, X_train)
    create_music(music_pred, data['sample_rate'], tempo, rhythm, tone)
    
main()

内容的提问来源于stack exchange,提问作者OdinX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:05:23