https://github.com/sameersegal/video-concat
Concatenate videos in Google Drive using FFMPEG and then places it back in Google Drive
https://github.com/sameersegal/video-concat
ecs-fargate google-drive-cli lambda-functions sqs-queue terraform video-processing
Last synced: 6 months ago
JSON representation
Concatenate videos in Google Drive using FFMPEG and then places it back in Google Drive
- Host: GitHub
- URL: https://github.com/sameersegal/video-concat
- Owner: sameersegal
- Created: 2020-09-30T06:32:45.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-06-24T10:19:12.000Z (almost 5 years ago)
- Last Synced: 2025-02-26T11:46:42.476Z (about 1 year ago)
- Topics: ecs-fargate, google-drive-cli, lambda-functions, sqs-queue, terraform, video-processing
- Language: HCL
- Homepage:
- Size: 467 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Video Concat
With every family video, we get more ambitious. It always is a frantic finish just before we need to play the video.
This project helps join/concatenate videos based on a sequence file. It get's triggered by API call and results in a final video published on Google Drive.
Video processing takes time (CPU intensive) and a lot of space. On Mac Air, you are severly constrained. That's why I picked AWS ECS with Fargate.
I have used Terraform to quickly bring up the infrastructure and destroy when I am done. It's perfect for infrequent use like Family events.
I assume you have an account with AWS and have a brief understanding of AWS, Terraform, Docker, etc
## Get Started
1. Ensure you have the pre-requisites:
1. AWS CLI [downloaded](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) and configured (`aws configure`) with significant previlige to create all the infrastructure.
2. Terraform [downloaded](https://www.terraform.io/downloads.html) and in path.
3. Docker [downloaded](https://www.docker.com/get-started). (On a Mac, `brew cask install docker` worked instead of the regular `brew install docker`)
2. Generate a Service Account to access Google Drive
1. Follow the instructions [here](https://developers.google.com/identity/protocols/oauth2/service-account) to generate the json file and store it as `cotainer/credentials.json`
2. Remember to [enable](https://console.developers.google.com/apis/api/drive.googleapis.com/overview) Google Drive Apis for this service account.
3. On the `output` Google Drive folder, remember to add the email of the Service Account as a collaborator with edit previleges.
3. Create the lambda function:
1. `npm install` in the lambda folder
2. zip and create the package
```
zip -r ../trigger.zip main.js node_modules package.json
```
3. Build the infrastructure
1. The following commands have to be run in the `terraform` folder
```
cd terraform
```
1. Create a `my.tfvars` file with the following:
```
ecr_name = "ss-video-concate"
ecs_cluster_name = "ss-video-cluster"
ecs_service_name = "videoconcat-service"
ecs_task_definition_family = "VideoConcat"
docker_image = "705594476693.dkr.ecr.ap-south-1.amazonaws.com/ss-video-concate"
sqs_queue_name = "video-queue"
api_path = "video-concat"
```
Note: You may not have the docker_image just yet. Put in a dummy value (like above) and then update it after running the docker steps.
2. Run terraform
```
terraform init
terraform plan --var-file="my.tfvars" -out=tfplan
terraform apply "tfplan"
```
3. Note down the output variables from above
```
base_url = "https://XXXXXXXX.execute-api.ap-south-1.amazonaws.com/test"
queue_url = "https://sqs.ap-south-1.amazonaws.com/XXXXXXXXXXXX/video-queue"
```
3. Create and publish the docker image
1. Create the docker image locally
```
docker build -t video-concat .
```
2. Follow the instructions on the ECR page to publish. It will substitute variables correctly.
```
aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin XXXXXXXXXX.dkr.ecr.ap-south-1.amazonaws.com
docker build -t ss-video-concate .
docker tag ss-video-concate:latest XXXXXXXXXX.dkr.ecr.ap-south-1.amazonaws.com/ss-video-concate:latest
docker push XXXXXXXXXX.dkr.ecr.ap-south-1.amazonaws.com/ss-video-concate:latest
```
3. Copy the URI / ARN for the latest docker image and update the file `my.tfvars` created in step 3.2
4. And you are done! If you are stuck, keep repeating steps 4.1-4.3 to get the configuration right.
5. Test your setup by creating a POST request to your API:
1. Find the input and output folder IDs. It's part that comes after the *folders* in a Google Drive link
```
https://drive.google.com/drive/folders/XXXXXXXXXXXXXgtj9wZG3HIcb6b1dLLqg
```
2. Create a sequence file by mention each file name on a separate line. Remember that the sequence file should be a simple text file and not Google Docs or Doc or Docx or any other complex format. (We will be doing `cat sequence` in our script.)
```
Opening.mp4
Video 1.mp4
Video 2.mp4
Credits.mp4
```
3. Generate the video by calling the API:
```
curl --location --request POST 'https://XXXXXXXX.execute-api.ap-south-1.amazonaws.com/test/video-concat/' \
--header 'Content-Type: application/json' \
--data-raw '{
"input_folder": "XXXXXXXXXXTgtj9wZG3HIcb6b1dLLqg",
"output_folder": "XXXXXXXXXjjLvduXwQM4j5lPHY7_6z6a",
"sequence_file_name": "sequence",
"template_file_name": "template",
"output_file_prefix": "Short-Video-",
"skip_download":"false",
"delete_files":"template%20sequence"
}'
```
4. Check CloudWatch logs to see if there are any errors in Lambda or ECS. If not, you will see your video in the `output` folder
6. When done you can destroy your infrastructure:
```
terraform plan --var-file="my.tfvars" -destroy -out=tfplan
terraform apply "tfplan"
```
### How does this work?

1. User's `POST` request is passed on to a Lambda Function via API Gateway
2. The Lambda Function posts an event to SQS Queue and updates the ECS service's desired count to 1
3. The ECS container reads from the queue in a while loop, until there are no messages.
4. The ECS container downloads all the files in the `input` folder. It expects the sequence file to be present here.
5. It uses `ffmpeg` to concatenate the videos using [ffmpeg filters](https://ffmpeg.org/ffmpeg-filters.html#concat)
6. It then pushes the final video to the `output` folder
7. It then deletes the message from the queue, and checks for another message
### Example Sequence & Templates
```
Beginning Video with Music.mp4
Mom \& Dad.mp4
Relative1.mov Name 1 mandala2.png #032B60 SN2s.jpg
Relative2.MOV Name 2 mandala2.png #8F3A6F SN14s.jpg
Relative3.mov Name 3 mandala1.png #70094A SN14s.jpg
Relative4.mov Name 4 mandala2.png #3750A8 SN13s.jpg
Relative5.mp4 Name 5 mandala3.png #A67761 SN1s.jpg
Relative6.mp4 Name 6 mandala3.png #A67761 SN1s.jpg
Ending Video with Music.mp4
```
```
if [[ -z "$arg3" ]];
then
ffmpeg -hide_banner -i "$arg1" -t 10 \
-c:a aac -c:v libx264 -crf 23 \
-filter_complex "[0:v]scale=1920x1080:force_original_aspect_ratio=decrease,pad=1920:1080:0:0:color=black, \
setdar=16/9,setsar=1/1,fps=fps=30,format=yuv420p; \
[0:a]loudnorm=i=-24:tp=-2:lra=7" \
"$i.ts"
else
ffmpeg -hide_banner -i "$arg1" -t 10 -i $arg3 -i $arg5 \
-filter_complex "[0:v]scale=1600:900:force_original_aspect_ratio=decrease,pad=1920:1080:320:0:color=$arg4,setdar=16/9,setsar=1/1,fps=fps=30,format=yuv420p[V1]; \
[V1][1:v]overlay=(overlay_w/2)*-1+40:main_h-(overlay_h/2)-40[V2]; \
[V2][2:v]overlay=0:450-(overlay_h/2)[V3]; \
[V3]drawtext=fontfile=./Sanchez-Regular.ttf: text='$arg2': fontcolor=white: fontsize=64: x=(w-text_w)/2: y=(h-90-(text_h/2)); \
[0:a]loudnorm=i=-24:tp=-2:lra=7" \
-c:a aac -c:v libx264 -crf 23 \
"$i.ts"
fi
```
More templates [here](templates/)
### Further Reading
I found the following tutorials and articles very helfpul while working on this project:
1. [Better Together: Amazon ECS and AWS Lambda | AWS Compute Blog](https://aws.amazon.com/blogs/compute/better-together-amazon-ecs-and-aws-lambda/)
2. [How to manage Terraform state. A guide to file layout, isolation, and… | by Yevgeniy Brikman | Gruntwork](https://blog.gruntwork.io/how-to-manage-terraform-state-28f5697e68fa)
3. [Copy all files in a folder from Google Drive to AWS S3 (Example)](https://coderwall.com/p/rckamw/copy-all-files-in-a-folder-from-google-drive-to-aws-s3)
4. [Docker Images : Part I - Reducing Image Size](https://www.ardanlabs.com/blog/2020/02/docker-images-part1-reducing-image-size.html)
5. [Fargate as Batch Service. AWS Fargate can be a useful service for… | by Ava Chen | Aug, 2020 | Medium](https://medium.com/@avachen2005/fargate-as-batch-service-31a896ec1917)
6. [Serverless Applications with AWS Lambda and API Gateway | Terraform - HashiCorp Learn](https://learn.hashicorp.com/tutorials/terraform/lambda-api-gateway)
7. [Why does AWS Lambda need to pass ecsTaskExecutionRole to ECS task](https://serverfault.com/questions/945596/why-does-aws-lambda-need-to-pass-ecstaskexecutionrole-to-ecs-task)
* https://stackoverflow.com/questions/58686844/ecs-task-not-starting-stopped-cannotpullcontainererror-error-response-from
* https://medium.com/@paweldudzinski/creating-aws-ecs-cluster-of-ec2-instances-with-terraform-893c15d1116
8. [EFS and ECS](https://aws.amazon.com/blogs/containers/developers-guide-to-using-amazon-efs-with-amazon-ecs-and-aws-fargate-part-1/)
9. [FFMPEG documentation]()