archiving community contributions on YouTube: unpublished captions, title and description translations and caption credits
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

80 lines
3.4 KiB

  1. import requests
  2. from json import loads
  3. def getmetadata(vid):
  4. params = (
  5. ("v", vid),
  6. )
  7. wpage = requests.get("https://www.youtube.com/watch", params=params)
  8. wptext = wpage.text
  9. initplay = None
  10. initdata = None
  11. recvids = set()
  12. recchans = set()
  13. recmixes = set()
  14. recplayl = set()
  15. for line in wptext.splitlines():
  16. if line.strip().startswith('window["ytInitialPlayerResponse"] = '):
  17. initplay = loads(line.split('window["ytInitialPlayerResponse"] = ', 1)[1].strip()[:-1])
  18. if initplay["playabilityStatus"]["status"] == "ERROR":
  19. print(vid, "unavailable")
  20. return False, recvids, recchans, recmixes, recplayl
  21. if "endscreen" in initplay.keys():
  22. for el in initplay["endscreen"]["endscreenRenderer"]:
  23. elint = el["endscreenElementRenderer"]
  24. if elint["style"] == "VIDEO":
  25. recvids.add(elint["endpoint"]["watchEndpoint"]["videoId"])
  26. elif elint["style"] == "CHANNEL":
  27. recchans.add(elint["endpoint"]["browseEndpoint"]["browseId"])
  28. elif elint["style"] == "PLAYLIST":
  29. recvids.add(elint["endpoint"]["watchEndpoint"]["videoId"])
  30. recplayl.add(elint["endpoint"]["watchEndpint"]["playlistId"])
  31. if "captions" in initplay.keys():
  32. ccenabled = "contribute" in initplay["captions"]["playerCaptionsRenderer"]
  33. else:
  34. ccenabled = False # if captions information is not present, community contributions are not enabled
  35. recchans.add(initplay["videoDetails"]["channelId"])
  36. elif line.strip().startswith('window["ytInitialData"] = '):
  37. initdata = loads(line.split('window["ytInitialData"] = ', 1)[1].strip()[:-1])
  38. if "contents" in initdata.keys(): #prevent exception
  39. for recmd in initdata["contents"]["twoColumnWatchNextResults"]["secondaryResults"]["secondaryResults"]["results"]:
  40. #auto is like the others
  41. if "compactAutoplayRenderer" in recmd.keys():
  42. recmd = recmd["compactAutoplayRenderer"]["contents"][0]
  43. if "compactVideoRenderer" in recmd.keys():
  44. recvids.add(recmd["compactVideoRenderer"]["videoId"])
  45. recchans.add(recmd["compactVideoRenderer"]["channelId"])
  46. elif "compactPlaylistRenderer" in recmd.keys():
  47. recplayl.add(recmd["compactPlaylistRenderer"]["playlistId"])
  48. recvids.add(recmd["compactPlaylistRenderer"]["navigationEndpoint"]["watchEndpoint"]["videoId"])
  49. recchans.add(recmd["compactPlaylistRenderer"]["shortBylineText"]["navigationEndpoint"]["browseEndpoint"]["browseId"])
  50. elif "compactRadioRenderer" in recmd.keys(): #mix playlist
  51. recmixes.add(recmd["compactRadioRenderer"]["playlistId"])
  52. # todo: find out if channels can be suggested
  53. if initplay and initdata:
  54. break
  55. return ccenabled, recvids, recchans, recmixes, recplayl
  56. if __name__ == "__main__":
  57. from sys import argv
  58. vidl = argv
  59. vidl.pop(0)
  60. for video in vidl:
  61. print(getmetadata(video))