Minio and NATS based video converter (PoC) for Nextcloud
- nextcloud minio nats kubernetes video-conversion
Due to the current circumstances around COVID-19, my wife started to create more and more videos for her choirs for learning and greeting purposes.
For distribution, we use Nextcloud for file sharing. But some videos are really large. Streaming in different qualities is not possible and we don´t use youtube for data privacy reasons. So we had to convert the videos to a smaller, web optimized size to be (better) sharable. But her laptop is a bit older and even small videos take quite a long time to encode. And even with newer hardware a tool like Handbrake is nothing for my wife.
Before I started this proof of concept, we shared a directory between our two users. She placed a video there, I encoded it in 720p with my PC and placed the result again in this folder. We did this several time, every few days.
But this isn´t really a nice solution for the future. So wouldn´t it be great if she can make use of a folder where she can place videos for encoding? Then after some time the encoded result appears in this folder automatically.
Idea
Video (mp4) files uploaded into a folder should be automatically converted into a smaller 720p video as a copy besides the original file.
Some requirements:
- Integration with Nextcloud is a must
- I don´t want to write php code
Rough design:
- Minio as storage with bucket notifications configured for new files
- NATS as messaging system
- minnat-converter as application listening to this events, converting and storing the videos
- Integration in Nextcloud with adding minio bucket as S3 external storage
Setup
Because this project starts as a proof of concept I use my small kubernetes cluster at home to run this solution. So the setup described here needs the following components to be available.
- kubernetes cluster with a storage system included
- cert-manager set up
- ingress manager set up and domain pointing to kubernetes
- helm 3 cli on your local laptop
- k8s namespace: minnat-converter
Install NATS
For nats on kubernetes it is recommended to use the nats-operator.
I downloaded the operator yaml´s and modified them to point to the namespace minnat-converter
.
# setup nats-operator https://github.com/nats-io/nats-operator
kubectl apply -f nats-operator/00-prereqs.yaml
kubectl apply -f nats-operator/10-deployment.yaml
kubectl apply -f nats-operator/default-rbac.yaml
kubectl apply -f nats-operator/deployment.yaml
# setup nats server
kubectl apply -f nats.yaml
For local tests against the nats cluster within kubernetes one could use the command line tools from nats. This would look like the following.
go get github.com/nats-io/go-nats-examples/tools/nats-sub
go get github.com/nats-io/go-nats-examples/tools/nats-pub
export PATH=$PATH:$HOME/go/bin/
kubectl port-forward nats-1 4222
nats-sub -t "minio.files.put"
Install minio
For minio I use the official helm chart for a proper installation. See minio.yaml for configuration options including ingress and nats configuration.
# create minio secret with access-key and secret-key pair
kubectl create secret generic minio-keys --from-literal=accesskey=foobarbaz --from-literal=secretkey=foobarbazqux
helm install minio stable/minio -f k8s-setup/minio.yaml
# add bucket
mc config host add minnat https://<domain> <access-key> <secret-key>
mc mb minnat/videos
# enable bucketnotifcations for mp4 videos
mc event add minnat/videos arn:minio:sqs:home:_:nats --suffix .mp4 --event put
mc event list
Minnat-converter application
The application is based on micronaut. It uses https://github.com/bramp/ffmpeg-cli-wrapper and ffmpeg itself for conversion. Of course I use the official minio and nats/nats-streaming java sdk´s.
Finally the application is packaged as docker image and deployed to kubernetes.
Deployment minnat-converter
See k8s
folder for k8s deployment descriptors. For development and deployment I use skaffold. You can see
skaffold.yaml
for configuration. Basically it builds the docker image and deploys every yaml file in folder k8s
.
./gradlew clean build
skaffold run
configuration options
Environment variable | default value | description |
---|---|---|
MINNAT_NATS_HOST | ‘nats://nats:4222’ | Url to nats cluster |
MINNAT_NATS_CLIENTID | ‘minnat-converter’ | Nats clientId prefix |
MINNAT_NATS_CLUSTERID | ‘stan’ | Nats streaming clusterId |
MINNAT_NATS_SUBJECT | ‘minio.files.put’ | Nats subject to listen on events |
MINNAT_NATS_QUEUE_NAME | ‘minnat-converter’ | Nats queue name |
MINNAT_NATS_DURABLE_NAME | ‘minnat-converter’ | Nats durable name |
MINNAT_MINIO_HOST | ‘http://minio:9000' | Internal minio url |
MINNAT_MINIO_ACCESS_KEY | fetched from minio-keys secret, see [](./k8s/deployment.yaml) | |
MINNAT_MINIO_SECRET_KEY | fetched from minio-keys secret, see [](./k8s/deployment.yaml) | |
MINNAT_FILTER_PATTERN | ’.mp4’ | Only files ending with pattern will be converted |
MINNAT_CONVERTED_SUFFIX | ’-720p’ | Suffix added to converted files |
MINNAT_WORKING_DIRECTORY | ’/tmp’ | Temp directory for video files |
Conclusion and outlook
All code and configurations used above are available in the gitlab repo https://gitlab.com/cin/minnat-converter.
For a easter weekend site-project I have now a solution for video conversion and it works pretty good. Ok, there are no configuration options for the end user, error handling has to be improved and some more testing has to be done. But that is something for the next weekend :-)