Skip to content

Commit

Permalink
added v1 of combine videos to concatenate
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen G Pope authored and Stephen G Pope committed Dec 11, 2024
1 parent ffc1a82 commit f760fdf
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,13 @@ def wrapper(*args, **kwargs):
# version 1.0
from routes.v1.ffmpeg.compose import v1_ffmpeg_compose_bp
from routes.v1.media.transcribe import v1_media_transcribe_bp
from routes.v1.video.concatenate import v1_video_concatenate_bp
from routes.v1.toolkit.test import v1_toolkit_test_bp
from routes.v1.toolkit.authenticate import v1_toolkit_auth_bp

app.register_blueprint(v1_ffmpeg_compose_bp)
app.register_blueprint(v1_media_transcribe_bp)
app.register_blueprint(v1_video_concatenate_bp)
app.register_blueprint(v1_toolkit_test_bp)
app.register_blueprint(v1_toolkit_auth_bp)

Expand Down
52 changes: 52 additions & 0 deletions routes/v1/video/concatenate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from flask import Blueprint
from app_utils import *
import logging
from services.v1.video.concatenate import process_video_concatenate
from services.authentication import authenticate
from services.cloud_storage import upload_file

v1_video_concatenate_bp = Blueprint('v1_video_concatenate', __name__)
logger = logging.getLogger(__name__)

@v1_video_concatenate_bp.route('/v1/video/concatenate', methods=['POST'])
@authenticate
@validate_payload({
"type": "object",
"properties": {
"video_urls": {
"type": "array",
"items": {
"type": "object",
"properties": {
"video_url": {"type": "string", "format": "uri"}
},
"required": ["video_url"]
},
"minItems": 1
},
"webhook_url": {"type": "string", "format": "uri"},
"id": {"type": "string"}
},
"required": ["video_urls"],
"additionalProperties": False
})
@queue_task_wrapper(bypass_queue=False)
def combine_videos(job_id, data):
media_urls = data['video_urls']
webhook_url = data.get('webhook_url')
id = data.get('id')

logger.info(f"Job {job_id}: Received combine-videos request for {len(media_urls)} videos")

try:
output_file = process_video_concatenate(media_urls, job_id)
logger.info(f"Job {job_id}: Video combination process completed successfully")

cloud_url = upload_file(output_file)
logger.info(f"Job {job_id}: Combined video uploaded to cloud storage: {cloud_url}")

return cloud_url, "/v1/video/concatenate", 200

except Exception as e:
logger.error(f"Job {job_id}: Error during video combination process - {str(e)}")
return str(e), "/v1/video/concatenate", 500
51 changes: 51 additions & 0 deletions services/v1/video/concatenate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
import ffmpeg
import requests
from services.file_management import download_file

# Set the default local storage directory
STORAGE_PATH = "/tmp/"

def process_video_concatenate(media_urls, job_id, webhook_url=None):
"""Combine multiple videos into one."""
input_files = []
output_filename = f"{job_id}.mp4"
output_path = os.path.join(STORAGE_PATH, output_filename)

try:
# Download all media files
for i, media_item in enumerate(media_urls):
url = media_item['video_url']
input_filename = download_file(url, os.path.join(STORAGE_PATH, f"{job_id}_input_{i}"))
input_files.append(input_filename)

# Generate an absolute path concat list file for FFmpeg
concat_file_path = os.path.join(STORAGE_PATH, f"{job_id}_concat_list.txt")
with open(concat_file_path, 'w') as concat_file:
for input_file in input_files:
# Write absolute paths to the concat list
concat_file.write(f"file '{os.path.abspath(input_file)}'\n")

# Use the concat demuxer to concatenate the videos
(
ffmpeg.input(concat_file_path, format='concat', safe=0).
output(output_path, c='copy').
run(overwrite_output=True)
)

# Clean up input files
for f in input_files:
os.remove(f)

os.remove(concat_file_path) # Remove the concat list file after the operation

print(f"Video combination successful: {output_path}")

# Check if the output file exists locally before upload
if not os.path.exists(output_path):
raise FileNotFoundError(f"Output file {output_path} does not exist after combination.")

return output_path
except Exception as e:
print(f"Video combination failed: {str(e)}")
raise

0 comments on commit f760fdf

Please sign in to comment.