AWS Lambda subprocess OSError: [Errno 2] No such file or directory
<p>I'm trying to create a lambda function that makes collection of thumbnails from a video on amazon s3 using ffmpeg. ffmpeg binary is included into fuction package.</p>

<p>function code:</p>

<pre><code># -*- coding: utf-8 -*-

import stat
import shutil
import boto3
import logging
import subprocess as sp
import os
import threading

thumbnail_prefix = 'thumb_'
thumbnail_ext = '.jpg'
time_delta = 1
video_frames_path = 'media/videos/frames'

print('Loading function')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

lambda_tmp_dir = '/tmp'  # Lambda fuction can use this directory.

# ffmpeg is stored with this script.
# When executing ffmpeg, execute permission is requierd.
# But Lambda source directory do not have permission to change it.
# So move ffmpeg binary to `/tmp` and add permission.
ffmpeg_bin = "{0}/ffmpeg.linux64".format(lambda_tmp_dir)
shutil.copyfile('/var/task/ffmpeg.linux64', ffmpeg_bin)

os.chmod(ffmpeg_bin, 777)

# tried also:
# os.chmod(ffmpeg_bin, os.stat(ffmpeg_bin).st_mode | stat.S_IEXEC)

s3 = boto3.client('s3')


def get_thumb_filename(num):
    return '{prefix}{num:03d}{ext}'.format(prefix=thumbnail_prefix, num=num, ext=thumbnail_ext)


def create_thumbnails(video_url):
    i = 1
    filenames_list = []
    filename = None
    while i == 1 or os.path.isfile(os.path.join(os.getcwd(), get_thumb_filename(i-1))):
        if filename:
            filenames_list.append(filename)
        time = time_delta * (i - 1)
        filename = get_thumb_filename(i)
        print(ffmpeg_bin)
        if os.path.isfile(ffmpeg_bin):
            print('ok')
        sp.call(['sudo',
                 ffmpeg_bin,
                 '-ss',
                 str(time),
                 '-i',
                 video_url,
                 '-frames:v',
                 '1',
                 get_thumb_filename(i)])
        i += 1
    print(filenames_list)
    return filenames_list


def s3_upload_file(file_path, key, bucket, acl, content_type):
    file = open(file_path, 'r')
    s3.put_object(
        Bucket=bucket,
        ACL=acl,
        Body=file,
        Key=key,
        ContentType=content_type
    )
    logger.info("file {0} moved to {1}/{2}".format(file_path, bucket, key))


def s3_upload_files_in_threads(filenames_list, dir_path, bucket, s3path, acl, content_type):
    for filename in filenames_list:
        if os.path.isfile(os.path.join(dir_path, filename)):
            print(os.path.join(dir_path, filename))
        t = threading.Thread(target=s3_upload_file,
                             args=(os.path.join(dir_path, filename),
                                   '{0}/{1}'.format(s3path, filename),
                                   bucket,
                                   acl,
                                   content_type)).start()


def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    video_key = event['Records'][0]['s3']['object']['key']
    video_name = video_key.split('/')[-1].split('.')[0]
    video_url = 'http://{0}/{1}'.format(bucket, video_key)
    filenames_list = create_thumbnails(video_url)
    s3_upload_files_in_threads(filenames_list,
                               os.getcwd(),
                               bucket,
                               '{0}/{1}'.format(video_frames_path, video_name),
                               'public-read',
                               'image/jpeg')
    return
</code></pre>

<p>during the execution I get following logs:</p>

<pre><code>Loading function

/tmp/ffmpeg.linux64

ok

[Errno 2] No such file or directory: OSError
Traceback (most recent call last):
 File "/var/task/lambda_function.py", line 112, in lambda_handler
 filenames_list = create_thumbnails(video_url)
 File "/var/task/lambda_function.py", line 77, in create_thumbnails
 get_thumb_filename(i)])
 File "/usr/lib64/python2.7/subprocess.py", line 522, in call
 return Popen(*popenargs, **kwargs).wait()
 File "/usr/lib64/python2.7/subprocess.py", line 710, in __init__
 errread, errwrite)
 File "/usr/lib64/python2.7/subprocess.py", line 1335, in _execute_child
 raise child_exception
OSError: [Errno 2] No such file or directory
</code></pre>

<p>When I use the same sp.call() with the same ffmpeg binary on my ec2 instance it works fine. </p>

<p>The problem is not because of <code>ffmpeg</code>. The error is for <code>sudo</code> not found. Lambda instances do not come with <code>sudo</code>. Why do you need <code>sudo</code>? Can you print whatever you pass to <code>sp.call()</code>?</p>

python amazon-web-services ffmpeg aws-lambda