导入whisper库时触发TypeError:'NoneType'对象不可迭代
问题描述
尝试用Python生成字幕,复制创作者代码并安装所有依赖后,运行时在import whisper行触发如下错误:
Exception has occurred: TypeError argument of type 'NoneType' is not iterable File "D:\Python\Subtitle Generator\main.py", line 1, in <module> import whisper TypeError: argument of type 'NoneType' is not iterable
移除该行则提示whisper缺失,完整代码如下:
import whisper import os import cv2 from moviepy.editor import ImageSequenceClip, AudioFileClip, VideoFileClip from tqdm import tqdm class VideoTranscriber: def __init__(self, model_path, video_path): self.model = whisper.load_model(model_path) self.video_path = video_path self.audio_path = '' self.text_array = [] self.fps = 0 self.char_width = 0 def transcribe_video(self): print('Transcribing video') result = self.model.transcribe(self.audio_path) text = result["segments"][0]["text"] textsize = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.8, 2)[0] cap = cv2.VideoCapture(self.video_path) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) asp = 16/9 ret, frame = cap.read() width = frame[:, int(int(width - 1 / asp * height) / 2):width - int((width - 1 / asp * height) / 2)].shape[1] width = width - (width * 0.1) self.fps = cap.get(cv2.CAP_PROP_FPS) self.char_width = int(textsize[0] / len(text)) for j in tqdm(result["segments"]): lines = [] text = j["text"] end = j["end"] start = j["start"] total_frames = int((end - start) * self.fps) start = start * self.fps total_chars = len(text) words = text.split(" ") i = 0 while i < len(words): words[i] = words[i].strip() if words[i] == "": i += 1 continue length_in_pixels = len(words[i]) * self.char_width remaining_pixels = width - length_in_pixels line = words[i] while remaining_pixels > 0: i += 1 if i >= len(words): break length_in_pixels = len(words[i]) * self.char_width remaining_pixels -= length_in_pixels if remaining_pixels < 0: continue else: line += " " + words[i] line_array = [line, int(start) + 15, int(len(line) / total_chars * total_frames) + int(start) + 15] start = int(len(line) / total_chars * total_frames) + int(start) lines.append(line_array) self.text_array.append(line_array) cap.release() print('Transcription complete') def extract_audio(self, output_audio_path='test_videos/audio.mp3'): print('Extracting audio') video = VideoFileClip(self.video_path) audio = video.audio audio.write_audiofile(output_audio_path) self.audio_path = output_audio_path print('Audio extracted') def extract_frames(self, output_folder): print('Extracting frames') cap = cv2.VideoCapture(self.video_path) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) asp = width / height N_frames = 0 while True: ret, frame = cap.read() if not ret: break frame = frame[:, int(int(width - 1 / asp * height) / 2):width - int((width - 1 / asp * height) / 2)] for i in self.text_array: if N_frames >= i[1] and N_frames <= i[2]: text = i[0] text_size, _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.8, 2) text_x = int((frame.shape[1] - text_size[0]) / 2) text_y = int(height/2) cv2.putText(frame, text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2) break cv2.imwrite(os.path.join(output_folder, str(N_frames) + ".jpg"), frame) N_frames += 1 cap.release() print('Frames extracted') def create_video(self, output_video_path): print('Creating video') image_folder = os.path.join(os.path.dirname(self.video_path), "frames") if not os.path.exists(image_folder): os.makedirs(image_folder) self.extract_frames(image_folder) print("Video saved at:", output_video_path) images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")] images.sort(key=lambda x: int(x.split(".")[0])) frame = cv2.imread(os.path.join(image_folder, images[0])) height, width, layers = frame.shape clip = ImageSequenceClip([os.path.join(image_folder, image) for image in images], fps=self.fps) audio = AudioFileClip(self.audio_path) clip = clip.set_audio(audio) clip.write_videofile(output_video_path) # Example usage model_path = "base" video_path = "Videos/video.mov" output_video_path = "Videos/result.mov" transcriber = VideoTranscriber(model_path, video_path) transcriber.extract_audio() transcriber.transcribe_video() transcriber.create_video(output_video_path)
解决方案
- 重新安装指定版本的whisper:卸载现有包后安装稳定版本,执行命令:
pip uninstall openai-whisper -y pip install openai-whisper==20231117 - 确认Python环境一致性:检查运行代码的Python环境是否和安装依赖的环境一致,用
where python(Windows)或which python(Linux/macOS)查看路径,再用pip list确认whisper已安装在该环境中。 - 搭建干净虚拟环境:创建全新虚拟环境,仅安装必要依赖,避免包冲突:
pip install openai-whisper opencv-python moviepy tqdm - 手动下载模型:若自动下载失败,手动下载对应模型(如base模型),放到whisper默认缓存路径(Windows:
C:\Users\<用户名>\.cache\whisper;Linux/macOS:~/.cache/whisper),代码中指定本地模型路径。 - 调整代码初始化逻辑:将
self.model = whisper.load_model(model_path)从__init__方法移到transcribe_video方法开头,避免导入阶段就加载模型引发潜在问题。
内容的提问来源于stack exchange,提问作者Flimzy
相关产品推荐
相关产品推荐

