Encode a Local Video Library

Encode all the videos inside a local folder on you PC and save them back to it.

In this tutorial, you will learn how to select all the videos stored in a local folder on your computer, upload them to ByteNite, and let ByteNite encode them for you.

You will be able to download the encoded videos and save them back to your computer or to a cloud storage solution such as S3 or Dropbox.

πŸ“˜

Troubleshooting tip

In Python, you can diagnose API errors with response.raise_for_status().

Please check out the HTTP status codes in the API Reference for further details.

1. Get an access token

To begin, use your API key to obtain an access token.

import requests, json
import os
verbose = True
verboseprint = print if verbose else lambda *a, **k: None

api_key = 'BYTENITE_API_KEY' # << Paste here your API key

response = requests.post('https://api.bytenite.com/v1/auth/access_token', 
                             json={"apiKey": api_key})
access_token = response.json()['token'] # Your access token will be saved in this variable

2. Prepare your local folder

Specify the path to the folder on your computer where your videos are stored. You don't need to list your videos one by one; the following script will do that for you. The list sources will contain the paths to your videos.

my_dir = 'YOUR_FOLDER_PATH' # << Specify your local folder path here

# Search for videos in your folder
video_file_extensions = ('.264', '.3g2', '.3gp', '.3gp2', '.3gpp', '.3gpp2', '.3mm', '.3p2', '.60d', '.787', '.89', '.aaf', '.aec', '.aep', '.aepx', '.aet', '.aetx', '.ajp', '.ale', '.am', '.amc', '.amv', '.amx', '.anim', '.aqt', '.arcut', '.arf', '.asf', '.asx', '.avb', '.avc', '.avd', '.avi', '.avp', '.avs', '.avs', '.avv', '.axm', '.bdm', '.bdmv', '.bdt2', '.bdt3', '.bik', '.bin', '.bix', '.bmk', '.bnp', '.box', '.bs4', '.bsf', '.bvr', '.byu', '.camproj', '.camrec', '.camv', '.ced', '.cel', '.cine', '.cip', '.clpi', '.cmmp', '.cmmtpl', '.cmproj', '.cmrec', '.cpi', '.cst', '.cvc', '.cx3', '.d2v', '.d3v', '.dat', '.dav', '.dce', '.dck', '.dcr', '.dcr', '.ddat', '.dif', '.dir', '.divx', '.dlx', '.dmb', '.dmsd', '.dmsd3d', '.dmsm', '.dmsm3d', '.dmss', '.dmx', '.dnc', '.dpa', '.dpg', '.dream', '.dsy', '.dv', '.dv-avi', '.dv4', '.dvdmedia', '.dvr', '.dvr-ms', '.dvx', '.dxr', '.dzm', '.dzp', '.dzt', '.edl', '.evo', '.eye', '.ezt', '.f4p', '.f4v', '.fbr', '.fbr', '.fbz', '.fcp', '.fcproject', '.ffd', '.flc', '.flh', '.fli', '.flv', '.flx', '.gfp', '.gl', '.gom', '.grasp', '.gts', '.gvi', '.gvp', '.h264', '.hdmov', '.hkm', '.ifo', '.imovieproj', '.imovieproject', '.ircp', '.irf', '.ism', '.ismc', '.ismv', '.iva', '.ivf', '.ivr', '.ivs', '.izz', '.izzy', '.jss', '.jts', '.jtv', '.k3g', '.kmv', '.ktn', '.lrec', '.lsf', '.lsx', '.m15', '.m1pg', '.m1v', '.m21', '.m21', '.m2a', '.m2p', '.m2t', '.m2ts', '.m2v', '.m4e', '.m4u', '.m4v', '.m75', '.mani', '.meta', '.mgv', '.mj2', '.mjp', '.mjpg', '.mk3d', '.mkv', '.mmv', '.mnv', '.mob', '.mod', '.modd', '.moff', '.moi', '.moov', '.mov', '.movie', '.mp21', '.mp21', '.mp2v', '.mp4', '.mp4v', '.mpe', '.mpeg', '.mpeg1', '.mpeg4', '.mpf', '.mpg', '.mpg2', '.mpgindex', '.mpl', '.mpl', '.mpls', '.mpsub', '.mpv', '.mpv2', '.mqv', '.msdvd', '.mse', '.msh', '.mswmm', '.mts', '.mtv', '.mvb', '.mvc', '.mvd', '.mve', '.mvex', '.mvp', '.mvp', '.mvy', '.mxf', '.mxv', '.mys', '.ncor', '.nsv', '.nut', '.nuv', '.nvc', '.ogm', '.ogv', '.ogx', '.osp', '.otrkey', '.pac', '.par', '.pds', '.pgi', '.photoshow', '.piv', '.pjs', '.playlist', '.plproj', '.pmf', '.pmv', '.pns', '.ppj', '.prel', '.pro', '.prproj', '.prtl', '.psb', '.psh', '.pssd', '.pva', '.pvr', '.pxv', '.qt', '.qtch', '.qtindex', '.qtl', '.qtm', '.qtz', '.r3d', '.rcd', '.rcproject', '.rdb', '.rec', '.rm', '.rmd', '.rmd', '.rmp', '.rms', '.rmv', '.rmvb', '.roq', '.rp', '.rsx', '.rts', '.rts', '.rum', '.rv', '.rvid', '.rvl', '.sbk', '.sbt', '.scc', '.scm', '.scm', '.scn', '.screenflow', '.sec', '.sedprj', '.seq', '.sfd', '.sfvidcap', '.siv', '.smi', '.smi', '.smil', '.smk', '.sml', '.smv', '.spl', '.sqz', '.srt', '.ssf', '.ssm', '.stl', '.str', '.stx', '.svi', '.swf', '.swi', '.swt', '.tda3mt', '.tdx', '.thp', '.tivo', '.tix', '.tod', '.tp', '.tp0', '.tpd', '.tpr', '.trp', '.ts', '.tsp', '.ttxt', '.tvs', '.usf', '.usm', '.vc1', '.vcpf', '.vcr', '.vcv', '.vdo', '.vdr', '.vdx', '.veg','.vem', '.vep', '.vf', '.vft', '.vfw', '.vfz', '.vgz', '.vid', '.video', '.viewlet', '.viv', '.vivo', '.vlab', '.vob', '.vp3', '.vp6', '.vp7', '.vpj', '.vro', '.vs4', '.vse', '.vsp', '.w32', '.wcp', '.webm', '.wlmp', '.wm', '.wmd', '.wmmp', '.wmv', '.wmx', '.wot', '.wp3', '.wpl', '.wtv', '.wve', '.wvx', '.xej', '.xel', '.xesc', '.xfl', '.xlmv', '.xmv', '.xvid', '.y4m', '.yog', '.yuv', '.zeg', '.zm1', '.zm2', '.zm3', '.zmv')
your_videos = [item.name for item in os.scandir(my_dir) if item.is_file() and item.name.endswith(video_file_extensions)]
your_videos.sort()

# Prepare the filepaths
sources = [os.path.join(my_dir, v) for v in your_videos]

3. Generate the jobs

Create a new video encoding job for each of your_videos. You will need to save the assigned job IDs in a list to be able to access them later.

🚧

Automation Disclaimer

The code below and the following will generate an encoding job for each video file contained in your folder. You might want to double-check that you've selected the right folder and number of videos, to avoid wasting ByteChips.

# Set your API request parameters
app_template = "[email protected]"

# Initialize the list of job IDs and set the job names
n = len(your_videos)
job_ids = ['']*n
job_names = [s[:min(s.rfind("."),25)] for s in your_videos] # << Give your jobs whatever names you like

# Generate n jobs
for i in range(n):
    response = requests.post('http://api.bytenite.com/v1/customer/jobs', 
                         json={"name": job_names[i], "templateId": app_template},
                         headers={'Authorization': access_token})
    try:
        job_ids[i] = response.json()['job']['id']
        verboseprint(f"Job #{i} ({job_names[i]}) created - ID: {job_ids[i]}")
    except:
        print(f"CREATE ERROR: Job #{i} ({job_names[i]}): {response}")

4. Upload the videos

As also explained in "Encode a Local Video" guide, the local upload process with ByteNite requires three steps: retrieving a temporary URL from the data source setting response; uploading your video to the temporary URL; and notifying the server of the completed upload.

The following code automates this step for the n video encoding jobs.

data_source_body = {
    "dataSource": {
      "dataSourceDescriptor": "file",
      "params": {
        "@type": "type.googleapis.com/bytenite.data_source.LocalFileDataSource"
      }
    },
    "dataDestination": {
        "dataSourceDescriptor": "bucket",
    }
}

for i in range(n):
    response1, response2, response3 = "", "", ""
    
    # Set the data source and destination
    response1 = requests.post(f'https://api.bytenite.com/v1/customer/jobs/datasource/{job_ids[i]}', 
                         json=data_source_body, 
                         headers={'Authorization': access_token})
    
    try:
        # Retrieve a temp URL from the datasource response
        temp_url = response1.json()['job']['dataSource']['params']['tempUrl']
        
        # Upload the video to the temp URL
        verboseprint("Uploading...")
        with open(sources[i], mode='rb') as f:
            response2 = requests.put(temp_url, data=f, headers={'Content-Disposition': f'attachment; filename="{sources[i]}"'})
        
        # Notify ByteNite about the completed upload
        response3 = requests.post(f'http://api.bytenite.com/v1/customer/jobs/uploadcompleted/{job_ids[i]}', 
                                  json={}, 
                                  headers={'Authorization': access_token})
        verboseprint(f"Video #{i} ({job_names[i]}) uploaded")
    except:
        print(f'UPLOAD ERROR: Job #{i} ({job_names[i]}):')
        print(f'datasource: {response1} | put: {response2} | upload completed: {response3}\n')
        

5. Configure the encoding parameters

Load a JSON file containing the video parameters for your video encoding jobs using one of our Templates.

# Load a video encoding template
with open("path_to_your_template.json") as venc_template: # << Paste the path to your template here
    job_parameters = json.load(venc_template)

for i in range(n):
    response = requests.post(f'https://api.bytenite.com/v1/customer/jobs/params/{job_ids[i]}', 
                             json=job_parameters, 
                             headers={'Authorization': access_token})
    try:
        response.raise_for_status()
        verboseprint(f"Parameters for job #{i} ({job_names[i]}) set")
    except:
        print(f"PARAMETERS SETTING ERROR: Job #{i} ({job_names[i]}): {response}")

6. Start the jobs

Run your video encoding jobs.

for i in range(n):
    response = requests.post(f'https://api.bytenite.com/v1/customer/jobs/run/{job_ids[i]}',
                             headers={'Authorization': access_token})
    try:
        response.raise_for_status()
        verboseprint(f"Job #{i} ({job_names[i]}) started")
        
    except:
        print(f"RUN JOB ERROR: Job #{i} ({job_names[i]}): {response}")

7. Check the job statuses

Monitor the progress of your jobs and extract additional information if needed.

complete_count = 0

for i in range(n):
    response = requests.get(f'https://api.bytenite.com/v1/customer/jobs/{job_ids[i]}', 
                            headers={'Authorization': access_token}) 
    complete_count += 1 if response.json()['job']['state'] == 'JOB_STATE_COMPLETE' else 0
    
verboseprint(f"Completed jobs: {complete_count}/{n}")

8. Download your outputs to a local folder

When your jobs are completed, you can access the links to the output videos and download them.

Please keep in mind that if you've chosen our temporary storage option as the data destination, your output will be accessible for 48 hours starting from the moment the job is completed.

# Set the filepath for saving your output videos
out_dir = os.path.join(my_dir, 'encoded/')
os.makedirs(out_dir, exist_ok=True)

for i in range(n):
    # Get the results
    response = requests.get(f'https://api.bytenite.com/v1/customer/jobs/{job_ids[i]}/results', 
                        headers={'Authorization': access_token})
    results = response.json()['results']
    
    # Download the results from the temporary bucket and write them to your local directory
    out_file = os.path.join(out_dir, results[0]['name'])
    with open(out_file, 'wb') as out:
        r = requests.get(results[0]['link'], allow_redirects=True)
        out.write(r.content)
        
    verboseprint(f'File {out_file} written')

That's it!

You've now successfully encoded a local video library using ByteNite. Happy encoding!