为何yt-dlp命令行可截取视频,Python库却下载完整视频?
问题
命令行执行yt-dlp https://www.youtube.com/watch?v=MtN1YnoL46Q --download-sections "*00:02:05-00:02:10" --force-keyframes-at-cuts能正常下载指定视频片段,但用yt-dlp的Python库开发Flask API时,配置了对应的参数却还是下载完整视频。需求是直接截取视频返回,不想用FFmpeg后期裁剪,求排查代码问题。
代码如下:
from flask import Flask, make_response, request import yt_dlp from flask_cors import CORS app = Flask(__name__, static_folder='static') CORS(app, expose_headers=['Filename']) @app.route("/downloadpart/", methods=['POST']) def download_cut(): if request.method == 'POST': url = request.form.get('link') ydl_opts = {'format': 'best', 'download_sections' : "*00:02:05-00:02:10", 'force_keyframes_at_cuts' : True, } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(url, download=False) video_url = info_dict['url'] video_data = ydl.urlopen(video_url).read() headers = { 'Content-Type': 'video/mp4', } return make_response(video_data, 200, headers) except Exception as e: return make_response(e) return make_response("Invalid request", 400) if __name__ == '__main__': #app.run(debug=True) app.run(debug=False, host='0.0.0.0', port=5000)
问题原因
你代码的核心问题是绕开了yt-dlp的片段裁剪流程:
extract_info(url, download=False)只负责提取视频元数据和原始下载链接,不会触发任何裁剪操作- 后续你直接通过原始视频URL下载了完整视频,
download_sections和force_keyframes_at_cuts这两个参数根本没机会生效——它们是yt-dlp在下载阶段才会执行的处理逻辑,不是提取信息阶段的。
解决方案
要让裁剪参数生效,必须让yt-dlp完整执行下载+裁剪流程,然后捕获处理后的视频内容返回。下面是修正后的代码,通过将yt-dlp的输出导向内存缓冲区来实现:
from flask import Flask, make_response, request import yt_dlp from flask_cors import CORS import io import sys app = Flask(__name__, static_folder='static') CORS(app, expose_headers=['Filename']) @app.route("/downloadpart/", methods=['POST']) def download_cut(): if request.method == 'POST': url = request.form.get('link') ydl_opts = { 'format': 'best', 'download_sections': "*00:02:05-00:02:10", 'force_keyframes_at_cuts': True, 'quiet': True, # 关闭日志,避免干扰视频内容 'no_warnings': True, 'outtmpl': '-', # 将处理后的视频输出到stdout 'noplaylist': True, # 确保只处理单个视频 } try: output_buffer = io.BytesIO() # 临时重定向stdout到缓冲区 old_stdout = sys.stdout sys.stdout = output_buffer with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([url]) # 恢复stdout并读取缓冲区内容 sys.stdout = old_stdout output_buffer.seek(0) video_data = output_buffer.read() headers = { 'Content-Type': 'video/mp4', 'Content-Disposition': 'attachment; filename="cut_video.mp4"' } return make_response(video_data, 200, headers) except Exception as e: return make_response(str(e), 500) return make_response("Invalid request", 400) if __name__ == '__main__': app.run(debug=False, host='0.0.0.0', port=5000)
关键改动说明
- 移除了
extract_info直接拿原始链接的逻辑,改用ydl.download([url])让yt-dlp完整执行下载+裁剪 - 设置
outtmpl: '-'让处理后的视频输出到标准输出,再通过内存缓冲区捕获内容 - 添加
quiet和no_warnings避免日志内容混入视频数据 - 恢复标准输出,避免影响后续程序运行
这样就能让download_sections和force_keyframes_at_cuts参数正常生效,直接返回裁剪后的视频片段,不需要额外用FFmpeg后期处理。
内容的提问来源于stack exchange,提问作者JohnnySmith88
相关产品推荐
相关产品推荐

