image-20240608153236265

Youtube之类的视频网站中,总有许多想要下载的片断(fraction, portion, partial),因为整片下载耗时耗力又没必要。

Ai-China在网上找了找工具,有倒是有,就是找到的都是,要么过时不好用了(Github上的工具们),要么点开10多页广告还用不起(Youtube cutter们),要么只能下载360P清晰度且每月只允许下载几百M(streamable们)……

于是只好自己动手,基本原理就是使用yt-dlp下载,使用ffmpeg为指定的时间段随时编码。

步骤如下:

确保已安装必要工具和库

  • 安装 yt-dlp
1
pip install yt-dlp
  • 安装ffmpeg (根据操作系统不同):

    • 在 Ubuntu/Debian 上:
1
sudo apt-get install ffmpeg
  • 在 macOS 上:
1
brew install ffmpeg
  • 在 Windows 上,下载并安装 ffmpeg,然后将其添加到系统路径(PATH)中。

  • 在 Windows 上下载和安装 ffmpeg 可以按照以下步骤进行:

    步骤 1:下载 ffmpeg
    1. 打开你的浏览器并访问 FFmpeg官网
    2. 在页面上找到 “Windows” 选项卡,点击并选择适合的 Windows 版本。你可以直接前往 Gyan.dev FFmpeg Builds 进行下载。
    3. 在下载页面中,点击 “Release builds”,下载最新的 ffmpeg-release-essentials.zip 文件。(推荐下载 Essentials 版本)
    步骤 2:解压缩 ffmpeg
    1. 下载完成后,右键点击 ffmpeg-release-essentials.zip 文件,然后选择 “解压到当前文件夹” 或 “Extract Here”。你可以使用 Windows 内置的解压工具或第三方工具如 WinRAR、7-Zip。
    2. 解压后,你会看到一个文件夹,其中包含诸如 bin, doc, presetsLICENSE.txt 文件。
    步骤 3:配置系统环境变量
    1. 将解压后的文件夹移动到一个永久路径,比如 C:\ffmpeg
    2. 打开文件夹,进入 bin 文件夹,你会看到 ffmpeg.exe, ffplay.exe, 和 ffprobe.exe
    步骤 4:设置系统环境变量
    1. 找到 Windows “开始” 菜单,搜索 “环境变量” 并选择 “编辑系统环境变量”。
    2. 在弹出的 “系统属性” 窗口中,点击 “环境变量”。
    3. 在 “系统变量” 部分,找到并选择 Path,然后点击 “编辑”。
    4. 在 “编辑环境变量” 窗口中,点击 “新建” 并将 C:\ffmpeg\bin (即你的 ffmpeg.exe 所在的路径)添加进去,然后点击 “确定”。
    步骤 5:验证安装
    1. 打开命令提示符(按 Win + R,输入 cmd,然后按回车)。
    2. 在命令提示符中,输入:
    1
    ffmpeg -version

    ​ 如果安装成功,你会看到 ffmpeg 的版本信息及相关信息。

    示例命令

    一些简单的命令可以帮助你确认 ffmpeg 是否正常工作:

    1
    ffmpeg -version

    这将显示 ffmpeg 的版本信息。

    1
    ffmpeg -i input.mp4 output.avi

    这是一个简单的格式转换命令,将 input.mp4 转换为 output.avi

运行时报错

ModuleNotFoundError: No module named 'yt_dlp'

说明你的系统还没有安装 yt-dlp 模块。你可以按照以下步骤安装 yt-dlp

安装 yt-dlp
  1. 打开命令提示符
    • Win + R,输入 cmd,然后按回车。
  2. 安装 yt-dlp
    • 在命令提示符中运行如下命令:
1
pip install yt-dlp

如果你没有安装 pip,可以先按照以下步骤安装 pip

  • 安装 pip
1
python -m ensurepip --upgrade
验证 yt-dlp 安装

在命令提示符中执行以下命令来验证安装

1
python -m yt_dlp --version

如果命令返回 yt-dlp 版本号,表示安装成功。

运行时报错

yt_dlp.utils.DownloadError: ERROR: ffmpeg exited with code 4294967158

ffmpeg 退出代码 4294967158 这个错误,通常是由于 ffmpeg 可执行文件无法正常运行,可能的原因包括:

  1. ffmpeg 的路径设置不正确。
  2. ffmpeg 二进制文件损坏或不兼容。
  3. 系统没有权限访问 ffmpeg 可执行文件。

请按照以下步骤逐一排查并解决问题:

步骤 1:验证 ffmpeg 安装

确保 ffmpeg 已正确安装并在环境变量 PATH 中配置。

打开新的命令提示符窗口,输入以下命令并检查是否能看到 ffmpeg 的版本信息:

1
ffmpeg -version

如果上述命令返回 ffmpeg 的版本信息,则表示路径设置正确。如果没有,则需要检查 ffmpeg 是否正确下载并解压,确认路径是否添加到了系统的 PATH 中。

检查环境变量 PATH
  1. 检查 PATH 环境变量
    • 打开控制面板,转到 “系统和安全” -> “系统”,然后点击 “高级系统设置”。
    • 在系统属性窗口中,点击 “环境变量”。
    • 在 “系统变量” 部分,找到变量名为 Path,点击 “编辑”。
    • 确认 ffmpegbin 文件夹路径(例如 C:\ffmpeg\bin)在 Path 列表中。
  2. 添加 ffmpeg 路径(如果不存在):
    • 点击 “新建”,输入 ffmpegbin 文件夹路径(例如 C:\ffmpeg\bin)。
    • 点击 “确定” 保存更改,然后关闭所有窗口。
步骤 2:重新下载 ffmpeg

如果 ffmpeg 并没有正确运行,尝试重新下载并安装可能会解决这个问题。

  1. 访问 FFmpeg 官网 重新下载(推荐从 Gyan.dev 下载)。
  2. 解压下载的文件并确保将 bin 目录添加到系统 PATH 中。
其他可能的解决办法
  1. 如果你使用的是管理员用户账号,尝试以管理员身份运行命令提示符。
  2. 检查 ffmpeg 可执行文件是否有权限执行操作。
  3. 尝试在其他目录下运行脚本,避免路径中包含特殊字符或空格的问题。

如果问题仍然存在,可以尝试手动调用 ffmpeg 命令来测试。例如,先下载视频然后再用 ffmpeg 裁剪,以排除脚本问题。

运行时报错

ERROR: ffmpeg exited with code 4294967158

错误代码 4294967158 表示 ffmpeg 运行时出错,这通常和路径、权限或传递参数的问题相关。

[tcp @ 00000284704a8400] Connection attempt to 31.13.67.33 port 443 failed: Error number -138 occurred

ffmpeg 由于连接到 manifest.googlevideo.com 端口 443 失败而退出,错误码 -138 一般表示网络连接问题。这可能是网络不稳定、防火墙配置、VPN、代理服务等导致的问题。解决办法:在代码中添加 VPN proxy 项。

[download] Got error: 8746106 bytes read, 1254885 more expected

错误提示显示下载中途发生了不一致的问题:预期读取 10045991 字节,但实际只读取了 8746106 字节。这可能是由网络连接不稳定、服务器响应问题或者代理配置错误等引起的。

如果仅需要下载特定时间段的视频,直接指定时间段会更为高效。我们可以使用 yt-dlppostprocessor 来截取视频片段,而不是下载整个视频文件再进行裁剪。

此时可以使用 external_downloader_args 参数来传递给 ffmpeg,直接在下载时截取所需的时间段。

成品程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import os
import sys
import yt_dlp
import subprocess

def check_dependencies():
"""Check if yt-dlp and ffmpeg are installed, if not provide installation instructions."""
try:
import yt_dlp
except ImportError:
print("yt-dlp is not installed. Install it using 'pip install yt-dlp'")
sys.exit(1)

if os.system("ffmpeg -version") != 0:
print("ffmpeg is not installed or not added to PATH.")
if sys.platform.startswith("linux"):
print("On Linux, install it using 'sudo apt-get install ffmpeg'")
elif sys.platform == "darwin":
print("On macOS, install it using 'brew install ffmpeg'")
elif sys.platform == "win32":
print("On Windows, download ffmpeg from https://ffmpeg.org/download.html and add it to PATH")
sys.exit(1)

def main():
check_dependencies()

url = input("Enter the YouTube video URL: ")
start_time = input("Enter the start time (e.g., 00:00:10 for 10 seconds): ")
end_time = input("Enter the end time (e.g., 00:00:20 for 20 seconds): ")
output_format = input("Enter the output format (e.g., mp4, mkv): ")
output_path = input("Enter the output file path (e.g., output.mp4): ")

# Configure proxy settings (Modify the port no. if neccessary)
proxy = 'http://127.0.0.1:1080'
os.environ['http_proxy'] = proxy
os.environ['https_proxy'] = proxy

# yt-dlp options configuration
opts = {
'format': 'bestvideo+bestaudio',
'outtmpl': output_path,
'proxy': proxy,
'verbose': True, # 启用详细输出便于调试
'retries': 10, # 重试次数
'fragment_retries': 10, # 块重试次数
'continuedl': True, # 启用断点续传
'socket_timeout': 30, # 套接字超时时间(秒)
'external_downloader': 'ffmpeg',
'external_downloader_args': [ # 直接在下载时进行裁剪
'-ss', start_time,
'-to', end_time,
],
}

try:
with yt_dlp.YoutubeDL(opts) as ydl:
ydl.download([url])
print(f"Download and conversion complete, saved to {output_path}")

except yt_dlp.utils.DownloadError as e:
print(f"An error occurred with yt-dlp: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")

if __name__ == "__main__":
main()