如何用Python/Bash从TMDB API实时提取original_language和original_title?
批量为MKV电影添加TMDB元数据及海报的实现方案
准备工作
- 注册TMDB账号并获取API密钥(v3 Auth)
- 安装必要工具:
curl:Windows 10/11自带,或通过Git Bash获取jq:命令行JSON处理工具,可通过Chocolatey安装:choco install jqmkvtoolnix:包含mkvpropedit工具,用于修改MKV元数据,可通过Chocolatey安装:choco install mkvtoolnix- Python依赖:若使用Python方案,安装
requests库:pip install requests
方案一:Bash脚本实现(适合轻量批量处理)
核心思路:遍历MKV文件,提取文件名作为搜索关键词,调用TMDB API实时解析JSON字段,再用mkvpropedit写入元数据,可选下载并嵌入海报。
#!/bin/bash # 替换为你的TMDB API密钥 TMDB_API_KEY="your_api_key_here" # 搜索语言,可根据需求修改 SEARCH_LANG="zh-CN" # 中文URL编码函数(依赖Python) urlencode() { python -c "import urllib.parse; print(urllib.parse.quote('''$1'''))" } # 遍历当前目录下所有MKV文件 for mkv_file in *.mkv; do # 从文件名提取电影名称(去除.mkv后缀) movie_name=$(basename "$mkv_file" .mkv) echo "=== Processing $movie_name ===" # 调用TMDB搜索API,实时获取JSON响应 encoded_name=$(urlencode "$movie_name") tmdb_response=$(curl -s "https://api.themoviedb.org/3/search/movie?api_key=$TMDB_API_KEY&query=$encoded_name&language=$SEARCH_LANG") # 用jq提取目标字段 original_title=$(echo "$tmdb_response" | jq -r '.results[0].original_title') original_language=$(echo "$tmdb_response" | jq -r '.results[0].original_language') poster_path=$(echo "$tmdb_response" | jq -r '.results[0].poster_path') # 检查字段有效性 if [ "$original_title" = "null" ] || [ "$original_language" = "null" ]; then echo "❌ Failed to fetch data for $movie_name, skipping..." echo "" continue fi # 修改MKV元数据 echo "🔧 Updating metadata..." mkvpropedit "$mkv_file" \ --edit info \ --set "title=$original_title" \ --set "language=$original_language" \ --add-tag "ORIGINAL_TITLE=$original_title" \ --add-tag "ORIGINAL_LANGUAGE=$original_language" # 下载并嵌入海报(可选) if [ "$poster_path" != "null" ]; then echo "🖼️ Downloading poster..." poster_url="https://image.tmdb.org/t/p/original$poster_path" temp_poster="temp_poster.jpg" curl -s -o "$temp_poster" "$poster_url" echo "🔧 Embedding poster..." mkvpropedit "$mkv_file" \ --edit cover \ --add "$temp_poster" # 删除临时海报文件 rm "$temp_poster" fi echo "✅ Successfully updated $mkv_file" echo "" # 避免触发TMDB API调用限制,添加短暂延迟 sleep 0.5 done
方案二:Python脚本实现(适合复杂逻辑与错误处理)
核心思路:用Python的requests调用API,解析JSON数据,通过subprocess调用mkvpropedit修改元数据,支持更灵活的文件名处理和错误捕获。
import os import time import urllib.parse import requests import subprocess # 替换为你的TMDB API密钥 TMDB_API_KEY = "your_api_key_here" SEARCH_LANG = "zh-CN" def fetch_tmdb_metadata(movie_name): """调用TMDB API获取电影元数据""" encoded_name = urllib.parse.quote(movie_name) api_url = f"https://api.themoviedb.org/3/search/movie?api_key={TMDB_API_KEY}&query={encoded_name}&language={SEARCH_LANG}" try: response = requests.get(api_url, timeout=10) response.raise_for_status() data = response.json() except Exception as e: print(f"API请求失败: {str(e)}") return None # 取搜索结果的第一条 if not data.get("results"): return None first_result = data["results"][0] return { "original_title": first_result.get("original_title"), "original_language": first_result.get("original_language"), "poster_path": first_result.get("poster_path") } def update_mkv_metadata(mkv_path, original_title, original_language): """使用mkvpropedit修改MKV元数据""" cmd = [ "mkvpropedit", mkv_path, "--edit", "info", "--set", f"title={original_title}", "--set", f"language={original_language}", "--add-tag", f"ORIGINAL_TITLE={original_title}", "--add-tag", f"ORIGINAL_LANGUAGE={original_language}" ] try: subprocess.run(cmd, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"元数据修改失败: {e.stderr}") return False def embed_poster(mkv_path, poster_path): """下载并嵌入海报到MKV""" poster_url = f"https://image.tmdb.org/t/p/original{poster_path}" temp_poster = "temp_poster.jpg" try: # 下载海报 response = requests.get(poster_url, timeout=10) response.raise_for_status() with open(temp_poster, "wb") as f: f.write(response.content) # 嵌入海报 cmd = ["mkvpropedit", mkv_path, "--edit", "cover", "--add", temp_poster] subprocess.run(cmd, check=True, capture_output=True, text=True) # 删除临时文件 os.remove(temp_poster) return True except Exception as e: print(f"海报嵌入失败: {str(e)}") if os.path.exists(temp_poster): os.remove(temp_poster) return False def main(): # 遍历当前目录下的MKV文件 for filename in os.listdir("."): if not filename.endswith(".mkv"): continue mkv_path = os.path.abspath(filename) movie_name = os.path.splitext(filename)[0] print(f"\n=== 处理文件: {filename} ===") # 获取TMDB元数据 tmdb_data = fetch_tmdb_metadata(movie_name) if not tmdb_data: print("❌ 无法获取电影元数据,跳过") continue original_title = tmdb_data["original_title"] original_language = tmdb_data["original_language"] print(f"📌 原始标题: {original_title} | 原始语言: {original_language}") # 更新元数据 if not update_mkv_metadata(mkv_path, original_title, original_language): continue # 嵌入海报(可选) if tmdb_data["poster_path"]: print("🖼️ 开始嵌入海报...") embed_poster(mkv_path, tmdb_data["poster_path"]) print("✅ 文件处理完成") # 避免API调用超限 time.sleep(0.5) if __name__ == "__main__": main()
关键注意事项
- API调用限制:TMDB免费版API限制为每10秒40次请求,脚本中已添加
sleep延迟,若批量处理大量文件可适当延长延迟时间 - 文件名优化:若文件名包含年份(如
七武士 1954.mkv),可添加年份到搜索参数中,提高匹配准确性(可通过正则提取年份) - 字符集问题:Windows环境下建议使用Git Bash运行脚本,避免中文乱码;Python脚本默认支持UTF-8编码
- 测试建议:先选取单个MKV文件测试脚本功能,确认无误后再批量处理
内容的提问来源于stack exchange,提问作者Jim Julian
相关产品推荐
相关产品推荐

