Triggering renders from PHP
To trigger a Lambda render using PHP, you need to use the AWS SDK directly. Below you find a snippet showing the sample call to the AWS SDK. Note the following:
- You first need to complete the Lambda setup.
- Unstable API: The format that Remotion Lambda accepts can change in every version. You need to consult the history of this page to see the changes over time. This page always shows the latest version of the payload.
- Sending large input props (>200KB) is not supported with PHP at the moment.
remotion.phpphp<?php// We'll assume you use Composer, which will add autoload.phprequire_once __DIR__ . '/vendor/autoload.php';use Aws\Lambda\LambdaClient;<?php// Specify your environment variables in a .env file$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);$dotenv->load();// Specify the region you deployed to, for example "us-east-1"$region = $_ENV['REMOTION_APP_REGION'];// Specify your S3 bucket name$bucketName = $_ENV['REMOTION_APP_BUCKET'];// Specify the function you would like to call$functionName = $_ENV['REMOTION_APP_FUNCTION_NAME'];// Specify the URL to your Webpack bundle$serveUrl = $_ENV["REMOTION_APP_SERVE_URL"];$credentials = null;// If you don't have credentials but want to retrieve them using STS, use the AssumeRole featureif ($_ENV["REMOTION_APP_IS_ASSUME_ROLE"] === true) {$credentials = assumeRole($_ENV["REMOTION_APP_REGION"],$_ENV["REMOTION_APP_ROLE_ARN"], $_ENV["REMOTION_APP_ROLE_SESSION_NAME"]);}$client = LambdaClient::factory(['version' => 'latest','region' => $region,'credentials' => $credentials,]);// Specify your input props here$data = array("data" => "");$input = serializeInputProps($data,$region,"video-or-audio",null);// Note that the payload format may change in any version.// This is the structure of the latest version.$params = array("serveUrl" => $serverUrl,"inputProps" => $input,"composition" => "main","type" => "start","codec" => "h264",// Specify the Remotion version you are using"version" => "3.3.82","codec" => "h264","imageFormat" => "jpeg","crf" => null,"envVariables" => array(),"quality" => 80,"maxRetries" => 1,"privacy" => 'public',"logLevel" => 'info',"frameRange" => null,"outName" => null,"timeoutInMilliseconds" => 30000,"chromiumOptions" => array(),"scale" => 1,"everyNthFrame" => 1,"numberOfGifLoops" => 0,"concurrencyPerLambda" => 1,"downloadBehavior" => array("type" => "play-in-browser",),"muted" => false,"overwrite" => false,"audioBitrate" => null,"videoBitrate" => null,"webhook" => null,"forceHeight" => null,"forceWidth" => null,"bucketName" => null,"audioCodec" => null,"forceBucketName" => $bucketName,"dumpBrowserLogs" => false,);try {// Invoke the Lambda function$result = $client->invoke(['InvocationType' => 'RequestResponse','FunctionName' => $functionName,'Payload' => json_encode($params),]);$json_response = $result['Payload']->getContents();echo $json_response;} catch (AwsException $e) {// Handle the exceptionecho $e->getMessage();}function serializeInputProps($inputProps, string $region, string $type, ?string $userSpecifiedBucketName): array{try {$payload = json_encode($inputProps);$hash = randomHash();$MAX_INLINE_PAYLOAD_SIZE = 200000;if (strlen($payload) > $MAX_INLINE_PAYLOAD_SIZE) {throw new Exception(sprintf("Warning: inputProps are over %dKB (%dKB) in size.\n This is not currently supported.",round($MAX_INLINE_PAYLOAD_SIZE / 1000),ceil(strlen($payload) / 1024)));}return ['type' => 'payload','payload' => $payload,];} catch (Exception $e) {throw new Exception('Error serializing inputProps. Check it has no circular references or reduce the size if the object is big.');}}function assumeRole($region, $ARN, $sessionName){try {$stsClient = new Aws\Sts\StsClient(['region' => $region,'version' => 'latest',]);$result = $stsClient->AssumeRole(['RoleArn' => $ARN,'RoleSessionName' => $sessionName,]);return ['key' => $result['Credentials']['AccessKeyId'],'secret' => $result['Credentials']['SecretAccessKey'],'token' => $result['Credentials']['SessionToken'],];} catch (AwsException $e) {// Handle the exceptionecho $e->getMessage();return null;}}
remotion.phpphp<?php// We'll assume you use Composer, which will add autoload.phprequire_once __DIR__ . '/vendor/autoload.php';use Aws\Lambda\LambdaClient;<?php// Specify your environment variables in a .env file$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);$dotenv->load();// Specify the region you deployed to, for example "us-east-1"$region = $_ENV['REMOTION_APP_REGION'];// Specify your S3 bucket name$bucketName = $_ENV['REMOTION_APP_BUCKET'];// Specify the function you would like to call$functionName = $_ENV['REMOTION_APP_FUNCTION_NAME'];// Specify the URL to your Webpack bundle$serveUrl = $_ENV["REMOTION_APP_SERVE_URL"];$credentials = null;// If you don't have credentials but want to retrieve them using STS, use the AssumeRole featureif ($_ENV["REMOTION_APP_IS_ASSUME_ROLE"] === true) {$credentials = assumeRole($_ENV["REMOTION_APP_REGION"],$_ENV["REMOTION_APP_ROLE_ARN"], $_ENV["REMOTION_APP_ROLE_SESSION_NAME"]);}$client = LambdaClient::factory(['version' => 'latest','region' => $region,'credentials' => $credentials,]);// Specify your input props here$data = array("data" => "");$input = serializeInputProps($data,$region,"video-or-audio",null);// Note that the payload format may change in any version.// This is the structure of the latest version.$params = array("serveUrl" => $serverUrl,"inputProps" => $input,"composition" => "main","type" => "start","codec" => "h264",// Specify the Remotion version you are using"version" => "3.3.82","codec" => "h264","imageFormat" => "jpeg","crf" => null,"envVariables" => array(),"quality" => 80,"maxRetries" => 1,"privacy" => 'public',"logLevel" => 'info',"frameRange" => null,"outName" => null,"timeoutInMilliseconds" => 30000,"chromiumOptions" => array(),"scale" => 1,"everyNthFrame" => 1,"numberOfGifLoops" => 0,"concurrencyPerLambda" => 1,"downloadBehavior" => array("type" => "play-in-browser",),"muted" => false,"overwrite" => false,"audioBitrate" => null,"videoBitrate" => null,"webhook" => null,"forceHeight" => null,"forceWidth" => null,"bucketName" => null,"audioCodec" => null,"forceBucketName" => $bucketName,"dumpBrowserLogs" => false,);try {// Invoke the Lambda function$result = $client->invoke(['InvocationType' => 'RequestResponse','FunctionName' => $functionName,'Payload' => json_encode($params),]);$json_response = $result['Payload']->getContents();echo $json_response;} catch (AwsException $e) {// Handle the exceptionecho $e->getMessage();}function serializeInputProps($inputProps, string $region, string $type, ?string $userSpecifiedBucketName): array{try {$payload = json_encode($inputProps);$hash = randomHash();$MAX_INLINE_PAYLOAD_SIZE = 200000;if (strlen($payload) > $MAX_INLINE_PAYLOAD_SIZE) {throw new Exception(sprintf("Warning: inputProps are over %dKB (%dKB) in size.\n This is not currently supported.",round($MAX_INLINE_PAYLOAD_SIZE / 1000),ceil(strlen($payload) / 1024)));}return ['type' => 'payload','payload' => $payload,];} catch (Exception $e) {throw new Exception('Error serializing inputProps. Check it has no circular references or reduce the size if the object is big.');}}function assumeRole($region, $ARN, $sessionName){try {$stsClient = new Aws\Sts\StsClient(['region' => $region,'version' => 'latest',]);$result = $stsClient->AssumeRole(['RoleArn' => $ARN,'RoleSessionName' => $sessionName,]);return ['key' => $result['Credentials']['AccessKeyId'],'secret' => $result['Credentials']['SecretAccessKey'],'token' => $result['Credentials']['SessionToken'],];} catch (AwsException $e) {// Handle the exceptionecho $e->getMessage();return null;}}
Reference applications
2 reference projects are available:
- php-remotion. This is an application that invokes the Remotion Lambda function containing the minimum parameters to render a video.
- remotion-laravel is an application that serves a REST endpoint using Laravel PHP framework. This endpoint invokes the Remotion lambda function with the necessary parameters to render a video.
Both use remotion-app, which includes a Remotion composition and utility scripts for deploying and deleting Remotion Lambda infrastructure in AWS.
Bare PHP
Ensure that remotion-app is already deployed on your AWS Account.
The php-remotion application will call Remotion Lambda to render a video and contains the bare minimum parameters for Remotion's Lambda arguments. Once the parameters are constructed, they will be passed on to the AWS Lambda Client using the AWS PHP SDK. This project imitates the operation of rendermediaonlambda and uses composer.
Clone the project using:
bashgit clone https://github.com/alexfernandez803/php-remotion
bashgit clone https://github.com/alexfernandez803/php-remotion
remotion-serverless/php-remotion
bashcd remotion-serverless && cd php-remotion
bashcd remotion-serverless && cd php-remotion
bashphp composer.phar update
bashphp composer.phar update
The application has a .env file that needs to be populated for the video render to work properly. An .env.example has been included in the project containing example values.
.envbashREMOTION_APP_IS_ASSUME_ROLE="false"REMOTION_APP_REGION="ap-southeast-2"REMOTION_APP_BUCKET="remotionlambda-apsoutheast2-xxxxxx"REMOTION_APP_FUNCTION_NAME="remotion-render-3-3-78-mem2048mb-disk2048mb-240sec"REMOTION_APP_SERVE_URL="https://remotionlambda-apsoutheast2-qv16gcf02l.s3.ap-southeast-2.amazonaws.com/sites/remotion-render-app-3.3.78/index.html"REMOTION_APP_ROLE_ARN="arn:aws:iam::123456789012:role/xaccounts3access"REMOTION_APP_ROLE_SESSION_NAME="remotion_session_name"
.envbashREMOTION_APP_IS_ASSUME_ROLE="false"REMOTION_APP_REGION="ap-southeast-2"REMOTION_APP_BUCKET="remotionlambda-apsoutheast2-xxxxxx"REMOTION_APP_FUNCTION_NAME="remotion-render-3-3-78-mem2048mb-disk2048mb-240sec"REMOTION_APP_SERVE_URL="https://remotionlambda-apsoutheast2-qv16gcf02l.s3.ap-southeast-2.amazonaws.com/sites/remotion-render-app-3.3.78/index.html"REMOTION_APP_ROLE_ARN="arn:aws:iam::123456789012:role/xaccounts3access"REMOTION_APP_ROLE_SESSION_NAME="remotion_session_name"
REMOTION_APP_REGIONIs the AWS region you are using, e.gus-east-1.REMOTION_APP_IS_ASSUME_ROLEaccepts eithertrueorfalse. When set totruethe application the application calls the AWS STSAssumeRolecommand, retrieve thekey,secretandtokenand pass those credentials inLambdaClient::factory. Ensure thatREMOTION_APP_ROLE_ARNandREMOTION_APP_ROLE_SESSION_NAMEare provided when using this flag. This approach is appropriate if you want to deploy this application in AWS EC2. Roles are required to be set up for the application. Please refer to the Authenticating Lambda with EC2 guide and follow steps 1 to 4.Assume rolebash$credentials = NULL;if ($_ENV["REMOTION_APP_IS_ASSUME_ROLE"] === true) {$credentials = assumeRole($_ENV["REMOTION_APP_REGION"],$_ENV["REMOTION_APP_ROLE_ARN"], $_ENV["REMOTION_APP_ROLE_SESSION_NAME"]);}$client = LambdaClient::factory(['version' => 'latest','region' => $region,'credentials' => $credentials,]);Assume rolebash$credentials = NULL;if ($_ENV["REMOTION_APP_IS_ASSUME_ROLE"] === true) {$credentials = assumeRole($_ENV["REMOTION_APP_REGION"],$_ENV["REMOTION_APP_ROLE_ARN"], $_ENV["REMOTION_APP_ROLE_SESSION_NAME"]);}$client = LambdaClient::factory(['version' => 'latest','region' => $region,'credentials' => $credentials,]);
The following variables can be retrieved by completing the Lambda setup:
REMOTION_APP_BUCKET- Your bucket nameREMOTION_APP_FUNCTION_NAME- The name of your deployed function. Note that it changes on every Remotion version.REMOTION_APP_SERVE_URLis where your Webpack bundle is hosted.
When you use Remotion on an AWS EC2 instance, set the following env variables. To set up the required roles, please refer to the Authenticating Lambda with EC2 guide and follow steps 1 to 4.
REMOTION_APP_ROLE_ARNrepresents the ARN of the role which the application assume to render the video, for this instance it isremotion-ec2-executionroleARN fromstep 2on this guide.REMOTION_APP_ROLE_SESSION_NAMEa name to uniquely identify the role session when the same role is assumed by different principals.
Run the application by executing the command below:
Run applicationbashphp lambda-remotion-render.php
Run applicationbashphp lambda-remotion-render.php
Sample application responsebash{"bucketName":"remotionlambda-apsoutheast2-xxxx","renderId":"b2xhi715yn"}
Sample application responsebash{"bucketName":"remotionlambda-apsoutheast2-xxxx","renderId":"b2xhi715yn"}
Once the execution is successful, the API will responsd with the bucketName and renderId. These are metadata required to get the status the video render or retrieving video.
Laravel
This application can be executed on a local machine or computing instance, such as AWS EC2, to call Remotion Lambda and render a video. It includes the minimum parameters required for Remotion's Lambda arguments from a REST endpoint.
After constructing the parameters, they will be passed on to the AWS Lambda Client using the AWS PHP SDK. It also contains Laravel boilerplate code for setting up a REST endpoint that calls the Remotion Lambda. This project imitates the operation of renderMediaOnLambda() and uses Composer.
bashgit clone https://github.com/alexfernandez803/remotion-laravel
bashgit clone https://github.com/alexfernandez803/remotion-laravel
remotion-serverless/remotion-laravel
bashcd remotion-serverless && cd remotion-laravel
bashcd remotion-serverless && cd remotion-laravel
bashphp composer.phar update
bashphp composer.phar update
Refer to the bare PHP example for setting up the environment variables.
The application requires a database, and for this application, SQLLite is used. Therefore, the configuration details from the .env file need to be provided.
.env (continued)bashDB_CONNECTION=sqliteDB_DATABASE=database.sqlite
.env (continued)bashDB_CONNECTION=sqliteDB_DATABASE=database.sqlite
DB_CONNECTIONis the connection type that represents which database to use ie,MYSQLDB_DATABASEis the database name, for this instance this represents the absolute URL path of the SQLite database.
Create the database and table in SQLite defined in DB_DATABASE by executing the command below:
Create a database and tablebashphp artisan vendor:publish --tag=sanctum-migrations
Create a database and tablebashphp artisan vendor:publish --tag=sanctum-migrations
Run the application by executing the command below:
Run applicationbashphp artisan serve
Run applicationbashphp artisan serve
Send register requestbashcurl --location 'http://127.0.0.1:8000/api/register' \--header 'Content-Type: application/json' \--data-raw '{"name": "John Doe","email": "testuser@example.com","password": "L3tm3in@@","confirm_password": "L3tm3in@@"}'
Send register requestbashcurl --location 'http://127.0.0.1:8000/api/register' \--header 'Content-Type: application/json' \--data-raw '{"name": "John Doe","email": "testuser@example.com","password": "L3tm3in@@","confirm_password": "L3tm3in@@"}'
Log into the applicationbashcurl --location 'http://127.0.0.1:8000/api/login' \--header 'Content-Type: application/json' \--data-raw '{"email": "alex.frndz@gmail.com","password": "L3tm3in@@"}'
Log into the applicationbashcurl --location 'http://127.0.0.1:8000/api/login' \--header 'Content-Type: application/json' \--data-raw '{"email": "alex.frndz@gmail.com","password": "L3tm3in@@"}'
Sample responsejson{"success": true,"data": {"token": "2|ykXXPxXXX86pO4rXXXF49VhVXX34yGupU","name": "John Doe"},"message": "User login successfully."}
Sample responsejson{"success": true,"data": {"token": "2|ykXXPxXXX86pO4rXXXF49VhVXX34yGupU","name": "John Doe"},"message": "User login successfully."}
Render video requestbashcurl --location --request POST 'http://127.0.0.1:8000/api/renders' \--header 'Authorization: Bearer 2|ykXXPxXXX86pO4rXXXF49VhVXX34yGupU'
Render video requestbashcurl --location --request POST 'http://127.0.0.1:8000/api/renders' \--header 'Authorization: Bearer 2|ykXXPxXXX86pO4rXXXF49VhVXX34yGupU'
Example responsejson{"success": true,"data": {"bucketName": "remotionlambda-apsoutheast2-xxxxx","renderId": "745b9itxb2"},"message": "Render Successful."}
Example responsejson{"success": true,"data": {"bucketName": "remotionlambda-apsoutheast2-xxxxx","renderId": "745b9itxb2"},"message": "Render Successful."}
Checking progress
For retrieving the progress of a Lambda render, you need to send another request to the Lambda function. Currently we do not have instructions for it, as a reference you may see here for the payload that is being sent by the TypeScript SDK.