downloader.py 4.2 KB

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