diff --git a/app/routers/hosted_file.py b/app/routers/hosted_file.py index 4d79373..8b8b51d 100644 --- a/app/routers/hosted_file.py +++ b/app/routers/hosted_file.py @@ -1349,7 +1349,7 @@ async def create_video( # Run the ffmpeg command args = shlex.split(cmd) try: - subprocess.run(args, check=True, capture_output=True, text=True) + result = subprocess.run(args, check=True, capture_output=True, text=True) log.debug(result.stdout) except subprocess.CalledProcessError as e: log.exception('Error running ffmpeg command') @@ -1357,3 +1357,67 @@ async def create_video( # Return the new mp4 file for download return FileResponse(video_name, media_type='video/mp4', filename=f'{title_part_1}_{subtitle_part_1}.mp4') + + + +@router.post('/clip_video') +async def clip_video( + video_file: UploadFile = File(...), + start_time: str = Form(...), + end_time: str = Form(...), + reencode: bool = False, +): + log.setLevel(logging.DEBUG) + log.debug(locals()) + + video_file_name = video_file.filename + log.debug(video_file_name) + + (video_file_orig_filename, video_file_orig_extension) = os.path.splitext(video_file_name) + + # Save the uploaded audio file to a temporary directory + with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_video_file: + tmp_video_file.write(await video_file.read()) + tmp_video_file_orig_path = tmp_video_file.name + + # cmd = f"ls -lha /tmp" + # args = shlex.split(cmd) + # try: + # result = subprocess.run(args, check=True, capture_output=True, text=True) + # log.debug(result.stdout) + # except subprocess.CalledProcessError as e: + # log.exception('Error running ls command') + # return {'success': False, 'status_message': f'Error running ls command: {e}'} + + # Run the ffmpeg command to clip a video file based on the start and end times given + log.info('Run the ffmpeg command to clip a video file based on the start and end times given') + + with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_video_file_clip: + tmp_video_file_clip_path = tmp_video_file_clip.name + + # NOTE: It seems very important that the -y argument is used with ffmpeg run by subprocess.run(). Otherwise the process will hang. + # NOTE: This is a blocking process. It will take a while to complete. + if reencode: + new_video_file_clip_filename = f'{video_file_orig_filename}_[clip_reencode]{video_file_orig_extension}' + log.debug(new_video_file_clip_filename) + + cmd = f"ffmpeg -hide_banner -loglevel error -nostats -y -i {tmp_video_file_orig_path} -ss {start_time} -to {end_time} -c:v libx264 -crf 23 -maxrate 2M -bufsize 2M -c:a copy -movflags +faststart {tmp_video_file_clip_path}" + else: + new_video_file_clip_filename = f'{video_file_orig_filename}_[clip]{video_file_orig_extension}' + log.debug(new_video_file_clip_filename) + + cmd = f"ffmpeg -hide_banner -loglevel error -nostats -y -i {tmp_video_file_orig_path} -ss {start_time} -to {end_time} -c:v copy -c:a copy -movflags +faststart {tmp_video_file_clip_path}" + + log.debug(cmd) + + # Run the ffmpeg command + args = shlex.split(cmd) + try: + result = subprocess.run(args, check=True, capture_output=True, text=True) + log.debug(result.stdout) + except subprocess.CalledProcessError as e: + log.exception('Error running ffmpeg command') + return {'success': False, 'status_message': f'Error running ffmpeg command: {e}'} + + # Return the new mp4 file for download + return FileResponse(tmp_video_file_clip_path, media_type='video/mp4', filename=f'{new_video_file_clip_filename}')