downloader.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import sys
  2. import time
  3. import os
  4. import shutil
  5. from instagram_private_api_extensions import live, replay
  6. import logger
  7. class NoLivestreamException(Exception):
  8. pass
  9. class NoReplayException(Exception):
  10. pass
  11. def main(api_arg, record_arg, save_path_arg):
  12. global api
  13. global record
  14. global save_path
  15. global current_date
  16. global current_time
  17. global broadcast
  18. global mpd_url
  19. current_time = str(int(time.time()))
  20. current_date = time.strftime("%Y%m%d")
  21. api = api_arg
  22. record = record_arg
  23. save_path = save_path_arg
  24. get_user_info(record)
  25. def record_stream(broadcast):
  26. try:
  27. def check_status():
  28. print_status()
  29. mpd_url = (broadcast.get('dash_manifest')
  30. or broadcast.get('dash_abr_playback_url')
  31. or broadcast['dash_playback_url'])
  32. output_dir = save_path + '{}_{}_{}_{}_live_downloads'.format(current_date, record, broadcast['id'], current_time)
  33. dl = live.Downloader(
  34. mpd=mpd_url,
  35. output_dir=output_dir,
  36. user_agent=api.user_agent,
  37. max_connection_error_retry=2,
  38. duplicate_etag_retry=60,
  39. callback_check=check_status,
  40. mpd_download_timeout=10,
  41. download_timeout=10)
  42. except Exception as e:
  43. logger.log('[E] Could not start recording livestream: ' + str(e), "RED")
  44. logger.seperator("GREEN")
  45. sys.exit(1)
  46. try:
  47. logger.log('[I] Starting livestream recording:', "GREEN")
  48. logger.log('[I] Username : ' + record, "GREEN")
  49. logger.log('[I] MPD URL : ' + mpd_url, "GREEN")
  50. print_status(api, broadcast)
  51. logger.log('[I] Recording livestream... press [CTRL+C] to abort.', "GREEN")
  52. dl.run()
  53. stitch_video(dl, broadcast)
  54. except KeyboardInterrupt:
  55. logger.log("", "GREEN")
  56. logger.log('[W] Download has been aborted.', "YELLOW")
  57. logger.log("", "GREEN")
  58. if not dl.is_aborted:
  59. dl.stop()
  60. stitch_video(dl, broadcast)
  61. def stitch_video(dl, broadcast):
  62. logger.log('[I] Stitching downloaded files into video...', "GREEN")
  63. output_file = save_path + '{}_{}_{}_{}_live.mp4'.format(current_date, record, broadcast['id'], current_time)
  64. try:
  65. dl.stitch(output_file, cleartempfiles=False)
  66. logger.log('[I] Successfully stitched downloaded files.', "GREEN")
  67. logger.seperator("GREEN")
  68. sys.exit(0)
  69. except Exception as e:
  70. logger.log('[E] Could not stitch downloaded files: ' + str(e), "RED")
  71. logger.seperator("GREEN")
  72. sys.exit(1)
  73. def get_user_info(record):
  74. try:
  75. logger.log('[I] Getting required user info for user "' + record + '"...', "GREEN")
  76. user_res = api.username_info(record)
  77. user_id = user_res['user']['pk']
  78. except Exception as e:
  79. logger.log('[E] Could not get user info: ' + str(e), "RED")
  80. logger.seperator("GREEN")
  81. sys.exit(1)
  82. get_livestreams(user_id)
  83. get_replays(user_id)
  84. def get_livestreams(user_id):
  85. try:
  86. logger.log('[I] Checking for ongoing livestreams...', "GREEN")
  87. broadcast = api.user_broadcast(user_id)
  88. if (broadcast is None):
  89. raise NoLivestreamException('There are no livestreams available.')
  90. else:
  91. record_stream(broadcast)
  92. except NoLivestreamException as e:
  93. logger.log('[W] ' + str(e), "YELLOW")
  94. except Exception as e:
  95. if (e.__class__.__name__ is not NoLivestreamException):
  96. logger.log('[E] Could not get livestreams info: ' + str(e), "RED")
  97. logger.seperator("GREEN")
  98. sys.exit(1)
  99. def get_replays(user_id):
  100. try:
  101. logger.log('[I] Checking for available replays...', "GREEN")
  102. user_story_feed = api.user_story_feed(user_id)
  103. broadcasts = user_story_feed.get('post_live_item', {}).get('broadcasts', [])
  104. except Exception as e:
  105. logger.log('[E] Could not get replay info: ' + str(e), "RED")
  106. logger.seperator("GREEN")
  107. sys.exit(1)
  108. try:
  109. if (len(broadcasts) == 0):
  110. raise NoReplayException('There are no replays available.')
  111. else:
  112. logger.log("[I] Available replays have been found to download, press [CTRL+C] to abort.", "GREEN")
  113. logger.log("", "GREEN")
  114. for index, broadcast in enumerate(broadcasts):
  115. exists = False
  116. for directory in (os.walk(save_path).next()[1]):
  117. if (str(broadcast['id']) in directory) and ("_live_" not in directory):
  118. logger.log("[W] Already downloaded a replay with ID '" + str(broadcast['id']) + "', skipping...", "GREEN")
  119. exists = True
  120. if exists is False:
  121. current = index + 1
  122. logger.log("[I] Downloading replay " + str(current) + " of " + str(len(broadcasts)) + " with ID '" + str(broadcast['id']) + "'...", "GREEN")
  123. current_time = str(int(time.time()))
  124. output_dir = save_path + '{}_{}_{}_{}_replay_downloads'.format(current_date, record, broadcast['id'], current_time)
  125. dl = replay.Downloader(
  126. mpd=broadcast['dash_manifest'],
  127. output_dir=output_dir,
  128. user_agent=api.user_agent)
  129. replay_saved = dl.download(save_path + '{}_{}_{}_{}_replay.mp4'.format(current_date, record, broadcast['id'], current_time), cleartempfiles=False)
  130. if (len(replay_saved) == 1):
  131. logger.log("[I] Finished downloading replay " + str(current) + " of " + str(len(broadcasts)) + ".", "GREEN")
  132. logger.log("", "GREEN")
  133. else:
  134. logger.log("[W] No output video file was made, please merge the files manually.", "RED")
  135. logger.log("[W] Check if ffmpeg is available by running ffmpeg in your terminal.", "RED")
  136. logger.log("", "GREEN")
  137. logger.log("[I] Finished downloading available replays.", "GREEN")
  138. logger.seperator("GREEN")
  139. sys.exit(0)
  140. except NoReplayException as e:
  141. logger.log('[W] ' + str(e), "YELLOW")
  142. logger.seperator("GREEN")
  143. sys.exit(0)
  144. except Exception as e:
  145. logger.log('[E] Could not save replay: ' + str(e), "RED")
  146. logger.seperator("GREEN")
  147. sys.exit(1)
  148. except KeyboardInterrupt:
  149. logger.log("", "GREEN")
  150. logger.log('[W] Download has been aborted.', "YELLOW")
  151. try:
  152. shutil.rmtree(output_dir)
  153. except Exception as e:
  154. logger.log("[E] Could not remove temp folder: " + str(e), "RED")
  155. sys.exit(1)
  156. sys.exit(0)
  157. def print_status(api, broadcast):
  158. heartbeat_info = api.broadcast_heartbeat_and_viewercount(broadcast['id'])
  159. viewers = broadcast.get('viewer_count', 0)
  160. started_mins, started_secs = divmod((int(time.time()) - broadcast['published_time']), 60)
  161. started_label = '%d minutes' % started_mins
  162. if started_secs:
  163. started_label += ' and %d seconds' % started_secs
  164. logger.log('[I] Viewers : ' + str(int(viewers)) + " watching", "GREEN")
  165. logger.log('[I] Airing time : ' + started_label, "GREEN")
  166. logger.log('[I] Status : ' + heartbeat_info['broadcast_status'].title(), "GREEN")
  167. logger.log("", "GREEN")