123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import os
- import shutil
- import re
- import glob
- import subprocess
- import json
- import sys
- try:
- import pil
- import logger
- import helpers
- from constants import Constants
- except ImportError:
- from . import pil
- from . import logger
- from . import helpers
- from .constants import Constants
- """
- The content of this file was originally written by https://github.com/taengstagram
- The code has been edited for use in PyInstaLive.
- """
- def _get_file_index(filename):
- """ Extract the numbered index in filename for sorting """
- mobj = re.match(r'.+\-(?P<idx>[0-9]+)\.[a-z]+', filename)
- if mobj:
- return int(mobj.group('idx'))
- return -1
- def assemble(user_called=True, retry_with_zero_m4v=False):
- try:
- ass_json_file = pil.assemble_arg if pil.assemble_arg.endswith(".json") else pil.assemble_arg + ".json"
- ass_mp4_file = os.path.join(pil.dl_path, os.path.basename(ass_json_file).replace("_downloads", "").replace(".json", ".mp4"))
- ass_segment_dir = pil.assemble_arg if not pil.assemble_arg.endswith(".json") else pil.assemble_arg.replace(".json", "")
- if pil.verbose:
- logger.plain("{}\n{}\n{}".format(ass_json_file, ass_mp4_file, ass_segment_dir))
- broadcast_info = {}
- if not os.path.isdir(ass_segment_dir) or not os.listdir(ass_segment_dir):
- logger.error('The segment directory does not exist or does not contain any files: %s' % ass_segment_dir)
- logger.separator()
- return
- if not os.path.isfile(ass_json_file):
- logger.warn("No matching json file found for the segment directory, trying to continue without it.")
- ass_stream_id = os.listdir(ass_segment_dir)[0].split('-')[0]
- broadcast_info['id'] = ass_stream_id
- broadcast_info['broadcast_status'] = "active"
- broadcast_info['segments'] = {}
- else:
- with open(ass_json_file) as info_file:
- try:
- broadcast_info = json.load(info_file)
- except Exception as e:
- logger.warn("Could not decode json file, trying to continue without it.")
- ass_stream_id = os.listdir(ass_segment_dir)[0].split('-')[0]
- broadcast_info['id'] = ass_stream_id
- broadcast_info['broadcast_status'] = "active"
- broadcast_info['segments'] = {}
- if broadcast_info.get('broadcast_status', '') == 'post_live':
- logger.error('Video segment files from replay downloads cannot be assembled.')
- return
- stream_id = str(broadcast_info['id'])
- segment_meta = broadcast_info.get('segments', {})
- if segment_meta:
- all_segments = [
- os.path.join(ass_segment_dir, k)
- for k in broadcast_info['segments'].keys()]
- else:
- all_segments = list(filter(
- os.path.isfile,
- glob.glob(os.path.join(ass_segment_dir, '%s-*.m4v' % stream_id))))
- all_segments = sorted(all_segments, key=lambda x: _get_file_index(x))
- sources = []
- audio_stream_format = 'assembled_source_{0}_{1}_mp4.tmp'
- video_stream_format = 'assembled_source_{0}_{1}_m4a.tmp'
- video_stream = ''
- audio_stream = ''
- has_skipped_zero_m4v = False
- if not all_segments:
- logger.error("No video segment files have been found in the specified folder.")
- logger.separator()
- return
- else:
- logger.info("Assembling video segment files from specified folder: {}".format(ass_segment_dir))
- for segment in all_segments:
- if not os.path.isfile(segment.replace('.m4v', '.m4a')):
- logger.warn('Audio segment not found: {0!s}'.format(segment.replace('.m4v', '.m4a')))
- continue
- if segment.endswith('-init.m4v'):
- logger.info('Replacing %s' % segment)
- segment = os.path.join(
- os.path.dirname(os.path.realpath(__file__)), 'repair', 'init.m4v')
- if segment.endswith('-0.m4v') and not retry_with_zero_m4v:
- has_skipped_zero_m4v = True
- continue
- video_stream = os.path.join(
- ass_segment_dir, video_stream_format.format(stream_id, len(sources)))
- audio_stream = os.path.join(
- ass_segment_dir, audio_stream_format.format(stream_id, len(sources)))
- file_mode = 'ab'
- with open(video_stream, file_mode) as outfile, open(segment, 'rb') as readfile:
- shutil.copyfileobj(readfile, outfile)
- with open(audio_stream, file_mode) as outfile, open(segment.replace('.m4v', '.m4a'), 'rb') as readfile:
- shutil.copyfileobj(readfile, outfile)
- if audio_stream and video_stream:
- sources.append({'video': video_stream, 'audio': audio_stream})
- for n, source in enumerate(sources):
- ffmpeg_binary = os.getenv('FFMPEG_BINARY', 'ffmpeg')
- cmd = [
- ffmpeg_binary, '-loglevel', 'warning', '-y',
- '-i', source['audio'],
- '-i', source['video'],
- '-c:v', 'copy', '-c:a', 'copy', ass_mp4_file]
- #fnull = open(os.devnull, 'w')
- fnull = None
- exit_code = subprocess.call(cmd, stdout=fnull, stderr=subprocess.STDOUT)
- if exit_code != 0:
- logger.warn("FFmpeg exit code not '0' but '{:d}'.".format(exit_code))
- if has_skipped_zero_m4v and not retry_with_zero_m4v:
- logger.binfo("*-0.m4v segment was detected but skipped, retrying to assemble video without "
- "skipping it.")
- os.remove(source['audio'])
- os.remove(source['video'])
- logger.separator()
- assemble(user_called, retry_with_zero_m4v=True)
- return
- else:
- logger.info('The video file has been generated: %s' % os.path.basename(ass_mp4_file))
- os.remove(source['audio'])
- os.remove(source['video'])
- if user_called:
- logger.separator()
- except Exception as e:
- logger.error("An error occurred: {:s}".format(str(e)))
- def organize_videos():
- # Find the files in the current directory.
- current_dir_files = os.listdir()
- # The Instagram videos are in MP4 format.
- video_format = ['mp4']
- # Find the MP4 files and save them in a variable called 'filenames'.
- filenames = [filename for filename in current_dir_files if filename.split('.')[-1] in video_format]
- if len(filenames) == 0:
- print('Detected no valid files in current directory.')
- return
- # We want a dictionary where the filenames are the keys and the usernames are the values.
- filenames_to_usernames = {}
- # Populate the dictionary by going through each filename and removing the undesired characters, leaving just the usernames.
- for filename in filenames:
- filename_parts = filename.split('_')[1:-3]
- usernames = '_'.join(filename_parts)
- filenames_to_usernames[filename] = usernames
-
- # The usernames are the values of the filenames_to_usernames dictionary.
- usernames = set(filenames_to_usernames.values())
- # Make a folder for each username.
- for username in usernames:
- if not os.path.isdir(username):
- os.mkdir(username)
- # Move the videos into the folders
- for filename, username in filenames_to_usernames.items():
- shutil.move(filename, username)
- # Can also do os.rename(filename, '{}/{}'.format(username, filename))
- num_videos_moved = len(filenames_to_usernames.keys())
- print("{} videos moved successfully.".format(num_videos_moved))
|