downloader.py 6.5 KB

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