运行Reddit视频合并脚本时FFmpeg仅输出版本信息,如何修复?
问题修复方案
核心问题分析
- Reddit视频URL获取错误:直接使用
submission.url得到的是视频网页链接,并非实际视频文件地址,导致下载的是网页而非视频,文件自然损坏。 - 视频下载不完整:
requests.get直接写入大文件易因网络问题中断,引发文件损坏。 - FFmpeg命令无效:冗余参数
-strict experimental在新版FFmpeg中已无需使用,且未对文件名添加引号,若文件名含空格会导致命令解析失败,仅输出版本信息。 - 资源未正确释放与临时文件未清理:临时视频文件未被删除,且
cv2.VideoCapture占用文件可能导致后续操作异常。
修复步骤与代码修改
1. 正确获取Reddit视频源地址
替换视频URL提取逻辑,从submission.media['reddit_video']中获取实际视频文件的fallback_url:
video_urls = [] for submission in submissions: if submission.media and 'reddit_video' in submission.media: video_url = submission.media['reddit_video']['fallback_url'] video_urls.append(video_url)
2. 分块下载视频避免损坏
修改download_video函数,分块写入文件提升稳定性:
def download_video(url, filename): with requests.get(url, stream=True) as response: response.raise_for_status() with open(filename, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk)
3. 修正FFmpeg命令
移除冗余参数,对文件名添加引号处理空格问题:
ffmpeg_cmd = f'ffmpeg -i "{output_filename}" -i "combined_audio.mp3" -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 "final_output.mp4"' os.system(ffmpeg_cmd)
4. 完整清理临时文件
在函数末尾添加临时视频文件的删除逻辑,确保资源释放后再删除:
# 清理所有临时文件 for i in range(len(video_urls)): temp_file = f'temp_video_{i}.mp4' if os.path.exists(temp_file): os.remove(temp_file) if os.path.exists("combined_audio.mp3"): os.remove("combined_audio.mp3")
完整修复后的代码
import praw import requests import cv2 import os from pydub import AudioSegment def download_video(url, filename): # 分块下载视频,避免文件损坏 with requests.get(url, stream=True) as response: response.raise_for_status() with open(filename, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) def combine_videos(video_urls, output_filename): video_clips = [] audio_clips = [] for i, url in enumerate(video_urls): temp_filename = f'temp_video_{i}.mp4' download_video(url, temp_filename) # 读取视频与音频 video_clip = cv2.VideoCapture(temp_filename) audio_clip = AudioSegment.from_file(temp_filename, format="mp4") video_clips.append(video_clip) audio_clips.append(audio_clip) if not video_clips: print("No video clips to combine.") return # 获取视频基础参数 frame_width = int(video_clips[0].get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video_clips[0].get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = video_clips[0].get(cv2.CAP_PROP_FPS) # 使用更兼容的编码格式 fourcc = cv2.VideoWriter_fourcc(*'avc1') output_clip = cv2.VideoWriter(output_filename, fourcc, fps, (frame_width, frame_height)) # 写入视频帧 for video_clip in video_clips: video_clip.set(cv2.CAP_PROP_POS_FRAMES, 0) # 重置视频读取指针 while True: ret, frame = video_clip.read() if not ret: break output_clip.write(frame) # 释放视频资源 for video_clip in video_clips: video_clip.release() output_clip.release() # 合并音频 combined_audio = sum(audio_clips) combined_audio.export("combined_audio.mp3", format="mp3") # 修正后的FFmpeg合并命令 ffmpeg_cmd = f'ffmpeg -i "{output_filename}" -i "combined_audio.mp3" -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 "final_output.mp4"' os.system(ffmpeg_cmd) # 清理所有临时文件 for i in range(len(video_urls)): temp_file = f'temp_video_{i}.mp4' if os.path.exists(temp_file): os.remove(temp_file) if os.path.exists("combined_audio.mp3"): os.remove("combined_audio.mp3") def main(): reddit = praw.Reddit( client_id='XXX', client_secret='XXX', user_agent='Reddit Video Downloader' ) subreddit_name = input("Enter the name of the subreddit: ") limit = int(input("Enter the number of videos to download: ")) subreddit = reddit.subreddit(subreddit_name) submissions = subreddit.hot(limit=limit) # 正确提取Reddit视频源地址 video_urls = [] for submission in submissions: if submission.media and 'reddit_video' in submission.media: video_url = submission.media['reddit_video']['fallback_url'] video_urls.append(video_url) if video_urls: output_filename = input("Enter the output filename (e.g., output.mp4): ") combine_videos(video_urls, output_filename) print("Videos combined successfully!") else: print("No Reddit videos found in the subreddit.") if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Oreo F
相关产品推荐
相关产品推荐

