使用Python同步视频时遇numpy.ndarray无__round__方法错误求助
解决librosa节拍检测中的TypeError问题
先看你碰到的核心报错:
TypeError: type numpy.ndarray doesn't define __round__ method
这个问题的根源很清晰——你加载音频时用了mono=False,得到的是立体声二维numpy数组(形状为(2, 采样点数)),但librosa.beat.beat_track函数只能处理单声道的一维数组,这就导致内部计算bpm时,试图对数组执行round()操作,直接触发了类型错误。
第一步:修复音频加载问题
把音频改成单声道模式即可,有两种实现方式:
方式1:直接加载为单声道
librosa.load默认就是单声道模式,所以可以直接去掉mono=False参数:
audio, sr = librosa.load('nasty.mp3', sr=None)
方式2:加载后转单声道
如果后续需要保留立体声数据做其他操作,可以先加载立体声,再转换为单声道用于节拍检测:
audio, sr = librosa.load('nasty.mp3', sr=None, mono=False) # 转换为单声道音频 mono_audio = librosa.to_mono(audio) # 用单声道音频检测节拍 tempo, beat_frames = librosa.beat.beat_track(y=mono_audio, sr=sr)
第二步:优化视频循环逻辑(可选)
你当前的视频循环逻辑是每次把片段翻倍,不仅效率低,还可能导致片段时长远超需求。可以直接计算循环次数,一次性生成目标片段:
required_duration = beat_times[-1] clip_duration = 2 # 你截取的子片段时长 # 计算需要循环的次数,加1保证时长足够覆盖音频 loop_count = int(required_duration // clip_duration) + 1 # 批量生成循环片段 subclip = concatenate_videoclips([video.subclip(0, 2)] * loop_count) # 最后修剪到音频时长 subclip = subclip.subclip(0, required_duration)
第三步:其他注意事项
- 建议升级
librosa到最新版本,旧版本对多声道的处理可能存在bug,执行pip install --upgrade librosa即可。 - Pexels API返回的视频链接可能有有效期,如果遇到视频无法加载的问题,可以先把视频下载到本地再处理。
修改后的完整代码
import json import random import requests import librosa from moviepy.editor import VideoFileClip, concatenate_videoclips # Fetch multiple random videos from Pexels API response = requests.get("https://api.pexels.com/videos/search?query=jumping", headers={"Authorization": "563492ad6f91700001000001ffe8bbcab84343649c1acaaad1a446d9"}) response_json = json.loads(response.text) video_urls = [v['video_files'][0]['link'] for v in response_json['videos']] random.shuffle(video_urls) # Load audio file as mono and detect beats audio, sr = librosa.load('nasty.mp3', sr=None) tempo, beat_frames = librosa.beat.beat_track(y=audio, sr=sr) beat_times = librosa.frames_to_time(beat_frames, sr=sr) audio_duration = beat_times[-1] # Prepare a list to store the subclips subclips = [] # Process first 5 videos for i, video_url in enumerate(video_urls[:5]): # Load video file video = VideoFileClip(video_url) # Cut the first 2 seconds of the video clip_segment = video.subclip(0, 2) clip_duration = clip_segment.duration # Calculate loop count and create looped clip loop_count = int(audio_duration // clip_duration) + 1 subclip = concatenate_videoclips([clip_segment] * loop_count) # Trim the subclip to match the audio duration subclip = subclip.subclip(0, audio_duration) subclip = subclip.set_audio(audio) subclips.append(subclip) final_video = concatenate_videoclips(subclips) final_video.write_videofile("final_video.mp4")
内容的提问来源于stack exchange,提问作者Mykhaylo Official
相关产品推荐
相关产品推荐

