downloader.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import codecs
  2. import logging
  3. import sys, time
  4. from socket import timeout
  5. from instagram_private_api_extensions import live
  6. import logger
  7. class NoBroadcastException(Exception):
  8. pass
  9. def main(apiArg, recordArg, savePathArg):
  10. global api
  11. global record
  12. global savePath
  13. global currentDate
  14. global currentTime
  15. global broadcast
  16. global mpd_url
  17. currentTime = str(int(time.time()))
  18. currentDate = time.strftime("%Y%m%d")
  19. api = apiArg
  20. record = recordArg
  21. savePath = savePathArg
  22. getUserInfo(record)
  23. def recordStream(broadcast):
  24. try:
  25. def check_status():
  26. printStatus()
  27. return heartbeat_info['broadcast_status'] not in ['active', 'interrupted']
  28. mpd_url = (broadcast.get('dash_manifest')
  29. or broadcast.get('dash_abr_playback_url')
  30. or broadcast['dash_playback_url'])
  31. outputDir = savePath + '{}_{}_{}_{}_downloads'.format(currentDate ,record, broadcast['id'], currentTime)
  32. dl = live.Downloader(
  33. mpd=mpd_url,
  34. output_dir=outputDir,
  35. user_agent=api.user_agent,
  36. max_connection_error_retry=2,
  37. duplicate_etag_retry=60,
  38. callback_check=check_status,
  39. mpd_download_timeout=10,
  40. download_timeout=10)
  41. except Exception as e:
  42. logger.log('[E] Could not start recording broadcast: ' + str(e), "RED")
  43. logger.seperator("GREEN")
  44. sys.exit(0)
  45. try:
  46. viewers = broadcast.get('viewer_count', 0)
  47. started_mins, started_secs = divmod((int(time.time()) - broadcast['published_time']), 60)
  48. started_label = '%d minutes and ' % started_mins
  49. if started_secs:
  50. started_label += '%d seconds' % started_secs
  51. logger.log('[I] Starting broadcast recording:', "GREEN")
  52. last_stream = open("last_stream.html", "w")
  53. last_stream.write('<b>Username:</b> {}<br><b>MPD URL:</b> <a href="{}">LINK</a><br><b>Viewers:</b> {}<br><b>Missing:</b> {}'
  54. .format(record, mpd_url, str(int(viewers)), started_label))
  55. last_stream.close()
  56. logger.log('[I] Username : ' + record, "GREEN")
  57. logger.log('[I] MPD URL : ' + mpd_url, "GREEN")
  58. printStatus(api, broadcast)
  59. logger.log('[I] Recording broadcast... press [CTRL+C] to abort.', "GREEN")
  60. dl.run()
  61. stitchVideo(dl, broadcast)
  62. except KeyboardInterrupt:
  63. logger.log('', "GREEN")
  64. logger.log('[I] Aborting broadcast recording...', "GREEN")
  65. if not dl.is_aborted:
  66. dl.stop()
  67. stitchVideo(dl, broadcast)
  68. def stitchVideo(dl, broadcast):
  69. logger.log('[I] Stitching downloaded files into video...', "GREEN")
  70. output_file = savePath + '{}_{}_{}_{}.mp4'.format(currentDate ,record, broadcast['id'], currentTime)
  71. try:
  72. dl.stitch(output_file, cleartempfiles=False)
  73. logger.log('[I] Successfully stitched downloaded files!', "GREEN")
  74. logger.seperator("GREEN")
  75. sys.exit(0)
  76. except Exception as e:
  77. logger.log('[E] Could not stitch downloaded files: ' + str(e), "RED")
  78. logger.seperator("GREEN")
  79. sys.exit(0)
  80. def getUserInfo(record):
  81. try:
  82. user_res = api.username_info(record)
  83. user_id = user_res['user']['pk']
  84. getBroadcast(user_id)
  85. except Exception as e:
  86. logger.log('[E] Could not get user info for "' + record + '" : ' + str(e), "RED")
  87. logger.seperator("GREEN")
  88. sys.exit(0)
  89. def getBroadcast(user_id):
  90. try:
  91. logger.log('[I] Checking broadcast for "' + record + '"...', "GREEN")
  92. broadcast = api.user_broadcast(user_id)
  93. if (broadcast is None):
  94. raise NoBroadcastException('No broadcast available.')
  95. else:
  96. recordStream(broadcast)
  97. except NoBroadcastException as e:
  98. logger.log('[W] ' + str(e), "YELLOW")
  99. logger.seperator("GREEN")
  100. sys.exit(0)
  101. except Exception as e:
  102. if (e.__name__ is not NoBroadcastException):
  103. logger.log('[E] Could not get broadcast info: ' + str(e), "RED")
  104. logger.seperator("GREEN")
  105. sys.exit(0)
  106. def printStatus(api, broadcast):
  107. heartbeat_info = api.broadcast_heartbeat_and_viewercount(broadcast['id'])
  108. viewers = broadcast.get('viewer_count', 0)
  109. started_mins, started_secs = divmod((int(time.time()) - broadcast['published_time']), 60)
  110. started_label = '%d minutes and ' % started_mins
  111. if started_secs:
  112. started_label += '%d seconds' % started_secs
  113. logger.log('[I] Viewers : ' + str(int(viewers)) + " watching", "GREEN")
  114. logger.log('[I] Airing time : ' + started_label, "GREEN")
  115. logger.log('[I] Status : ' + heartbeat_info['broadcast_status'].title(), "GREEN")
  116. logger.log('', "GREEN")