def create_static_mix(static_mix_id): """ Task to create static mix and write to appropriate storage backend. :param static_mix_id: The id of the StaticMix to be processed """ # Mark as in progress try: static_mix = StaticMix.objects.get(id=static_mix_id) except StaticMix.DoesNotExist: # Does not exist, perhaps due to stale task print('StaticMix does not exist') return static_mix.status = TaskStatus.IN_PROGRESS static_mix.save() try: # Get paths directory = os.path.join(settings.MEDIA_ROOT, settings.SEPARATE_DIR, static_mix_id) filename = get_valid_filename(static_mix.formatted_name()) + '.mp3' rel_media_path = os.path.join(settings.SEPARATE_DIR, static_mix_id, filename) rel_path = os.path.join(settings.MEDIA_ROOT, rel_media_path) rel_path_dir = os.path.join(settings.MEDIA_ROOT, settings.SEPARATE_DIR, static_mix_id) pathlib.Path(directory).mkdir(parents=True, exist_ok=True) separator = get_separator(static_mix.separator, static_mix.separator_args, static_mix.bitrate, settings.CPU_SEPARATION) parts = { 'vocals': static_mix.vocals, 'drums': static_mix.drums, 'bass': static_mix.bass, 'other': static_mix.other } # Non-local filesystems like S3/Azure Blob do not support source_path() is_local = settings.DEFAULT_FILE_STORAGE == 'api.storage.FileSystemStorage' path = static_mix.source_path() if is_local else static_mix.source_url( ) if not settings.CPU_SEPARATION: # For GPU separation, do separation in separate process. # Otherwise, GPU memory is not automatically freed afterwards process_eval = Process(target=separator.create_static_mix, args=(parts, path, rel_path)) process_eval.start() try: process_eval.join() except SoftTimeLimitExceeded as e: # Kill process if user aborts task process_eval.terminate() raise e else: separator.create_static_mix(parts, path, rel_path) # Check file exists if os.path.exists(rel_path): static_mix.status = TaskStatus.DONE if is_local: # File is already on local filesystem static_mix.file.name = rel_media_path else: # Need to copy local file to S3/Azure Blob/etc. raw_file = open(rel_path, 'rb') content_file = ContentFile(raw_file.read()) content_file.name = filename static_mix.file = content_file # Remove local file os.remove(rel_path) # Remove empty directory os.rmdir(rel_path_dir) static_mix.save() else: raise Exception('Error writing to file') except FileNotFoundError as error: print(error) print('Please make sure you have FFmpeg and FFprobe installed.') static_mix.status = TaskStatus.ERROR static_mix.error = str(error) static_mix.save() except SoftTimeLimitExceeded: print('Aborted!') except Exception as error: print(error) static_mix.status = TaskStatus.ERROR static_mix.error = str(error) static_mix.save()
def create_dynamic_mix(dynamic_mix_id): """ Task to create dynamic mix and write to appropriate storage backend. :param dynamic_mix_id: The id of the audio track model (StaticMix) to be processed """ # Mark as in progress try: dynamic_mix = DynamicMix.objects.get(id=dynamic_mix_id) except DynamicMix.DoesNotExist: # Does not exist, perhaps due to stale task print('DynamicMix does not exist') return dynamic_mix.status = TaskStatus.IN_PROGRESS dynamic_mix.save() try: # Get paths directory = os.path.join(settings.MEDIA_ROOT, settings.SEPARATE_DIR, dynamic_mix_id) rel_media_path = os.path.join(settings.SEPARATE_DIR, dynamic_mix_id) file_prefix = get_valid_filename(dynamic_mix.formatted_prefix()) file_suffix = dynamic_mix.formatted_suffix() rel_path = os.path.join(settings.MEDIA_ROOT, rel_media_path) pathlib.Path(directory).mkdir(parents=True, exist_ok=True) separator = get_separator(dynamic_mix.separator, dynamic_mix.separator_args, dynamic_mix.bitrate, settings.CPU_SEPARATION) # Non-local filesystems like S3/Azure Blob do not support source_path() is_local = settings.DEFAULT_FILE_STORAGE == 'api.storage.FileSystemStorage' path = dynamic_mix.source_path( ) if is_local else dynamic_mix.source_url() # Do separation if not settings.CPU_SEPARATION: # For GPU separation, do separation in separate process. # Otherwise, GPU memory is not automatically freed afterwards process_eval = Process(target=separator.separate_into_parts, args=(path, rel_path)) process_eval.start() try: process_eval.join() except SoftTimeLimitExceeded as e: # Kill process if user aborts task process_eval.terminate() raise e else: separator.separate_into_parts(path, rel_path) # Check all parts exist if exists_all_parts(rel_path): rename_all_parts(rel_path, file_prefix, file_suffix) dynamic_mix.status = TaskStatus.DONE if is_local: save_to_local_storage(dynamic_mix, rel_media_path, file_prefix, file_suffix) else: save_to_ext_storage(dynamic_mix, rel_path, file_prefix, file_suffix) else: raise Exception('Error writing to file') except FileNotFoundError as error: print(error) print('Please make sure you have FFmpeg and FFprobe installed.') dynamic_mix.status = TaskStatus.ERROR dynamic_mix.error = str(error) dynamic_mix.save() except SoftTimeLimitExceeded: print('Aborted!') except Exception as error: print(error) dynamic_mix.status = TaskStatus.ERROR dynamic_mix.error = str(error) dynamic_mix.save()