An Interest In:
Web News this Week
- April 28, 2024
- April 27, 2024
- April 26, 2024
- April 25, 2024
- April 24, 2024
- April 23, 2024
- April 22, 2024
Some of Our Sources
View All SourcesGO - Funo Lambda para converter audio a partir do S3(AWS) - ffmpeg
Atuei em um projeto pessoal, onde necessitei fazer a converso de um arquivo wav(audio de qualidade maxima, sem compresso) para mp3.
Neste post, vou demonstrar o passo a passo, como fazer de forma "assncrona", a partir de um upload para um bucket no S3(servio de armazenamento de arquivos) da AWS.
No desenho abaixo, segue um contexto do que ser feito e explicado neste post:
Criando Buckets
Em seu console da AWS, v at o service S3, crie 2 novos buckets. O primeiro bucket, ser o destino do upload do arquivo de udio "bruto", no format .wav. O segundo, ser para o arquivo comprimido e convertido para .mp3. No meu caso, usei estes nomes:
Criando Lambda
Sim, vamos j proceder na criao da funo lambda que ser responsvel por converter os arquivos de audio bruto, para formado de audio compactado. Para isso, em seu AWS Console, na busca procuro por Lambda. Clique em Create Function
Vamos utilizar a linguagem GO, conforme a tela abaixo:
Permisses de acesso Lambda - S3
Ser necessrio a criao de uma Police, e atrel-la a Role criada na criao da lambda.
Para isso acessaremos o console do IAM, sem seguida vamos ao menu Polices > Add Police. Mudaremos o modo para JSON, e vamos inserir o cdigo a seguir:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup", "logs:PutLogEvents" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::mgm-wav-files/*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::mgm-mp3-files/*" } ]}
A poltica acima d permisso de leitura no bucket de arquivos wav e escrita no bucket para arquivos mp3, convertidos. Vamos salvar essa Police.
No console do IAM, vamos ao menu Roles, vamos selecionar a Role criada para a lambda. Em seguida, vamos em Add Permissions > atacch policies. Na buscar, buscar pelo nome da poltica criada e salvar.
Run time Lambda. O que isso?
As funes lambda, na linguagem Go(entre outras), rodam em um contexto de ambiente Linux, no caso da distribuio AWS Linux. Nesse contexto, precisamos "carregar" uma lib, que ser a responsvel por fazer a converso de udio.
Essa lib o FFMPEG. Que trata de vrios formatos de mdias, audio, video.
Para isso, utilizaremos uma feature das funes lambda na AWS, chamada Layer, traduzindo: camada
Com uma layer, conseguimos rodar algumas libs em tempo de execuo de uma ou mais funes lambda. Como?
Criando Layer FFMPEG
Vamos baixar os binrios desta lib em nossa mquina local, e transferir apenas o necessrio para um arquivo ZIP, que ser inserido em um Lambda Layer.
Para isso, vou utilizar o exemplo abaixo, de ambiente Linux/MacOS:
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xzwget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz.md5md5sum -c ffmpeg-release-amd64-static.tar.xz.md5tar xvf ffmpeg-release-amd64-static.tar.xz
Aps o download e descompactar o arquivo, vamos criar uma nova basta, para copiar o conteudo do binario do ffmpeg, e zipar o contedo:
mkdir -p ffmpeg/bincp ffmpeg-4.3.1-amd64-static/ffmpeg ffmpeg/bin/cd ffmpegzip -r ../ffmpeg.zip .
Agora, vamos criar uma nova Layer em nosso ambiente de Lambdas na AWS, anexando o arquivo zip criado no passo acima como no exemplo a seguir:
Anexando Layer FFMPEG a nossa funo Lambda
Vamos voltar ao menu Functions dentro de Lambda em nosso Console. Na aba code vamos descer a tela, e ir at a sesso Layers e clicar em Add Layer. Vamos preencher e selecionar o formulrio, como na imagem abaixo
E (FINALMENT) vamos ao nosso cdigo!
Para a linguagem Go, no temos um editor online em funes lambda na AWS. Por isso, vamos gerar nosso cdigo localmente, build-lo e subir um zip do mesmo via console.
Incio de tudo
package mainfunc main() {}
Em nosso ambiente local de desenvolvimento em Go, vamos criar uma nova pasta. Nesta pasta, iniciaremos o projeto com o famoso comando "go mod" para criar nosso arquivo de controle de mdulos go do Projeto.
Aps, iremos criar o arquivo main.go com o seguinte contedo:
package mainimport "github.com/aws/aws-lambda-go/lambda"func handler() {}func main() { lambda.Start(handler)}
Acima, importamos a biblioteca oficial lambda, para utilizao em Go. Criamos uma funo chamada handler onde vamos inserir nossa futura estrutura de converso de udio, e abaixo a funo main, apenas executa a funo handler em ambiente de execuo do Lambda.
Agora vamos carregar a biblioteca oficial do s3, para conectar no bucket que ir iniciar a funo(essa informao importante, pois o start traz informaes do bucket para a lambda). Em seguida, vamos criar um diretrio temporrio, dentro do ambiente de execuo da lambda, para fazer download do arquivo, onde possa ser manipulado. Em seguida realizar o download, utilizando um log para verificar:
package mainimport ( "context" "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "log" "os")func handler(_ context.Context, s3Event events.S3Event) { record := s3Event.Records[0] key := record.S3.Object.Key sess, _ := session.NewSession(&aws.Config{Region: &record.AWSRegion}) downloader := s3manager.NewDownloader(sess) file, err := os.Create(fmt.Sprintf("/tmp/%s", key)) if err != nil { panic(err) } defer file.Close() _, err = downloader.Download(file, &s3.GetObjectInput{ Bucket: &record.S3.Bucket.Name, Key: &key, }) if err != nil { panic(err) } log.Printf("Downloaded %s", file.Name())}func main() { lambda.Start(handler)}
Nossa funo handler, recebe 2 parmetros vindos de Context e events, libs da AWS que trazem informaes a respeito do bucket que inicia a lambda.
Neste ponto, interessante que faamos o primeiro upload do cdigo buildado, para realizar um teste "manual". Primeiro vamos criar o build dessa aplicao com o comando:
go build -o main
Em seguida, vamos empacotar o arquivo em um arquivo zip, para realizar o upload:
zip main.zip main
Agora vamos ao console, realizar o upload:
Criando Trigger
Antes de testarmos o cdigo, precisamos criar a trigger ou gatilho, que dar inicio a lambda que criamos.
Dentro da nossa funo, no console AWS vamos clicar em Add Trigger.
Vamos preencher o formulrio, conforme as 3 imagens abaixo:
Neste ponto, vamos selecionar o bucket dos arquivos brutos:
Em seguida selecionar todos os tipos de entrada de arquivos
Por final, vamos deixar um filtro para somente iniciar a lambda, para arquivos .wav
Primeiro teste
Agora, vamos ao nosso bucket, fazer um upload de arquivo .wav, e verificar o status no CloudWatch, e posteriormente verificar se o arquivo mp3 foi criado no outro bucket.
Acima vemos os 2 buckets utilizados em nosso projeto. Vamos acessar o mgm-wav-files para realizar o upload. Aps o upload, vamos acessar o CloudWatch, ir ao meno Logs > Logs Groups. L haver um grupo de log, com nome de nossa Lambda. Em nosso casso est assim:
Entrando em nosso log, vamos procurar se h a mensagem "Downloaded NOMEDOARQUIVO", como a seguir:
Neste caso, tudo certo, vamos continuar!
Convertando arquivo .wav com FFMPEG
Vamos utilizar a funciona a lib nativa Go OS, para utilizar a funo exec.Command, que nos possibilita rodar comandos em nvel de bash. E a partir dele, usar o ffmpeg para convertar o arquivo .wav para .mp3, gravando-o no diretrio temporrio criado anteriormente:
outputFile := strings.Replace(file.Name(), filepath.Ext(file.Name()), ".mp3", 1) cmd := exec.Command("ffmpeg", "-i", file.Name(), outputFile) out, err := cmd.CombinedOutput() if err != nil { log.Fatalf("cmd.Run() failed with %s
", err) } log.Printf("Execution output:
%s
", string(out)) output, err := os.Open(outputFile) if err != nil { panic(err) }
Gravando arquivo convertido em outro bucket
Agora, vamos acessar o arquivo criado, e fazer o upload para o bucket criado, apenas para receber os arquivos convertidos. O cdigo exemplo, existe na documentao da AWS:
//put mp3 file in converted bucket destinationBucket := "mgm-mp3-files" _, err = s3.New(sess).PutObject(&s3.PutObjectInput{ Bucket: &destinationBucket, Key: aws.String(filepath.Base(outputFile)), Body: output, }) log.Printf("Copied %s to %s", outputFile, record.S3.Bucket.Name)
Cdigo Final
package mainimport ( "context" "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "log" "os" "os/exec" "path/filepath" "strings")func handler(_ context.Context, s3Event events.S3Event) { record := s3Event.Records[0] key := record.S3.Object.Key sess, _ := session.NewSession(&aws.Config{Region: &record.AWSRegion}) //Download file to a temporary folder downloader := s3manager.NewDownloader(sess) file, err := os.Create(fmt.Sprintf("/tmp/%s", key)) if err != nil { panic(err) } defer file.Close() _, err = downloader.Download(file, &s3.GetObjectInput{ Bucket: &record.S3.Bucket.Name, Key: &key, }) if err != nil { panic(err) } log.Printf("Downloaded %s", file.Name()) //transform wav file to a compress mp3 file outputFile := strings.Replace(file.Name(), filepath.Ext(file.Name()), ".mp3", 1) cmd := exec.Command("ffmpeg", "-i", file.Name(), outputFile) out, err := cmd.CombinedOutput() if err != nil { log.Fatalf("cmd.Run() failed with %s
", err) } log.Printf("Execution output:
%s
", string(out)) output, err := os.Open(outputFile) if err != nil { panic(err) } //put mp3 file in converted bucket destinationBucket := "mgm-mp3-files" _, err = s3.New(sess).PutObject(&s3.PutObjectInput{ Bucket: &destinationBucket, Key: aws.String(filepath.Base(outputFile)), Body: output, }) log.Printf("Copied %s to %s", outputFile, record.S3.Bucket.Name)}func main() { lambda.Start(handler)}
PLUS - Mensagem assncrona de fim da atividade
Por final, vamos fazer com que, ao final da execuo do lambda, em caso de sucesso uma fila SQS seja abastecida com uma mensagem, para que consumidores(aplicativos, web, etc..) possam ser avisados do final do processo e disponibilizao do arquivo mp3 convertido.
Vamos agora ao console AWS, procurar por SQS. O servio simples de fila da prpria Amazon. Vamos criar um tpico, chamado mp3-ready
Agora, voltando a nossa funo lambda, vamos acessar o menu Add Destination.
Nosso formulrio deve ser preenchido destga maneira, escolhendo a fila SQS criada(A mensagem de falta de permisso para uso do SQS pelo lambda, ser solucionada no prximo passo)
Agora com nosso destino de lambda criado, precisamos dar permisso no IAM para nossa role de execuo da lambda, criar mensagem no tpico criado no SQS
Permisso lambda > SQS
No console do IAM, clicar no menu ROLES. Procurar pela role criada para a lambda. Dentro dessa role, vamos no menu Add Permissions > Atacch polices. Na busca, procurar por SQS, e escolher AmazonSQSFullAccess(sabemos que no o ideal rs.) e clicar em Add Permissions.
Original Link: https://dev.to/markgerald/go-lambda-para-converter-audio-a-partir-do-s3aws-ffmpeg-10jp
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To