probe_bilibili.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. """B站取数验证:DASH 分轨(视频 m4s + 音频 m4s)→ 下载 → ffmpeg 合并 → 验证有视频+音频。"""
  2. from __future__ import annotations
  3. import os
  4. import subprocess
  5. import sys
  6. import httpx
  7. import imageio_ffmpeg
  8. CRAW = "http://crawler.aiddit.com"
  9. def dl(url, path):
  10. # 用 curl,不跟随重定向(避免跟到 B站 mcdn 的 P2P 死节点,httpx 会卡在那)
  11. subprocess.run(["curl", "-s", "--connect-timeout", "15", "-m", "180",
  12. "-A", "Mozilla/5.0", "-e", "https://www.bilibili.com/",
  13. "-o", path, url], check=True)
  14. return os.path.getsize(path)
  15. def main():
  16. cid = sys.argv[1] if len(sys.argv) > 1 else "BV1qd4y1x76w"
  17. ff = imageio_ffmpeg.get_ffmpeg_exe()
  18. d = ((httpx.post(f"{CRAW}/crawler/bilibili/detail", json={"content_id": cid},
  19. timeout=40).json().get("data") or {}).get("data")) or {}
  20. v = d["video_url_list"][0]["video_url"]
  21. a = (d.get("voice_data") or {}).get("play_url")
  22. print("title:", (d.get("title") or "")[:30])
  23. print("视频轨:", v.split("?")[0].split("/")[-1])
  24. print("音频轨:", a.split("?")[0].split("/")[-1] if a else "无 voice_data.play_url")
  25. if not a:
  26. print("→ 没有音频轨,B站这条只有视频"); return 0
  27. nv = dl(v, "/tmp/bili_v.m4s")
  28. na = dl(a, "/tmp/bili_a.m4s")
  29. print(f"下载: 视频 {nv//1024//1024}MB, 音频 {na//1024}KB")
  30. r = subprocess.run([ff, "-y", "-i", "/tmp/bili_v.m4s", "-i", "/tmp/bili_a.m4s",
  31. "-c", "copy", "/tmp/bili_merged.mp4"], capture_output=True, text=True)
  32. import os
  33. if not os.path.exists("/tmp/bili_merged.mp4"):
  34. print("合并失败:", r.stderr[-300:]); return 1
  35. sz = os.path.getsize("/tmp/bili_merged.mp4")
  36. err = subprocess.run([ff, "-hide_banner", "-i", "/tmp/bili_merged.mp4"],
  37. capture_output=True, text=True).stderr
  38. streams = [l.strip() for l in err.splitlines() if "Stream #" in l]
  39. print(f"合并后 mp4: {sz//1024//1024}MB")
  40. print("流:")
  41. for s in streams:
  42. print(" ", s[:90])
  43. has_v = any("Video" in s for s in streams)
  44. has_a = any("Audio" in s for s in streams)
  45. print(f"\n结论:视频={'✅' if has_v else '❌'} 音频={'✅' if has_a else '❌'} "
  46. f"→ {'B站可拿到视频+音频,合并即可原生提炼' if has_v and has_a else 'B站缺轨'}")
  47. print("===BILIDONE===")
  48. return 0
  49. if __name__ == "__main__":
  50. raise SystemExit(main())