Setting Up Read-Only IAM Roles for FFmpeg on AWS S3

The job failed three times before anyone realized the FFmpeg process was trying to write to a bucket it could never touch.

When you run FFmpeg on AWS and pull media directly from S3, read-only IAM roles can make or break performance. A misconfigured policy means FFmpeg won’t even see the file, or worse—it gets stuck on permission errors that look like network timeouts. The fix is exact: tighten permissions for security, but let FFmpeg read without noise.

Why Read-Only Roles Matter

In AWS, every operation is bound by IAM. For FFmpeg workloads that only need source files from a bucket, allowing s3:GetObject is enough. Cutting out PutObject and DeleteObject blocks unwanted writes from your pipeline and hardens your security posture. This is crucial when working with large, sensitive video datasets or regulated environments.

Setting Up S3 Read-Only for FFmpeg

  1. Create an IAM policy with:
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": "s3:GetObject",
 "Resource": "arn:aws:s3:::your-bucket-name/*"
 }
 ]
}
  1. Attach the policy to the role your FFmpeg process assumes.
  2. Use AWS CLI or SDK to check role propagation before launching FFmpeg.

Direct S3 Input with FFmpeg

FFmpeg can read S3 URLs if the environment is configured for AWS credentials. Example:

ffmpeg -i "https://s3.amazonaws.com/your-bucket-name/video.mp4"-c:v libx264 output.mp4

For signed URLs, generate them via AWS SDK with expiration times short enough to prevent replay but long enough to finish the encode.

Performance Notes

Reading directly from S3 avoids the extra step of downloading to local storage, lowering IO overhead for ephemeral environments like AWS Lambda or transient EC2 instances. Combined with read-only roles, this improves security with zero cost to throughput.

When FFmpeg, AWS S3, and read-only IAM roles are set up without excess permissions, the pipeline becomes lean, fast, and resilient.

Configure it, run it, and watch it work. Test the setup live in minutes with hoop.dev.