Digital media comes in a variety of formats, each with its own set of specifications and codecs. Transcoding is what bridges the gap between different formats. Today, we'll be taking a deep dive into the world of transcoding; exploring its definition, importance, and how Transloadit can help you transcode your files in seconds.

A banner showing a mock terminal, with the text 'What is transcoding?' inputted into the console.

What is transcoding?

Put simply, transcoding is the process of transforming a media file of a certain format, into a media file of another format. As you can see in the diagram below, transcoding a file first involves decoding it into an intermediary uncompressed format (commonly PCM for audio or YUV for video). The intermediate file can then be freely encoded into whichever format is desired. Although, if you are transcoding into a lossy format, it is important to be aware of generation loss. This term stands for the degradation of quality that is caused by a small amount of information being lost upon each transcoding. With video transcoding, this loss of quality might be observed as small artifacts in the video, reminiscent of an early 2000's home video.

A flowchart showing an input file pointing into a transcoder, where the source format is decoded into an intermediary format, which is then encoded into the target format.

Why is transcoding necessary?

Now that we know what transcoding is, let's explore a few reasons why you might want to start transcoding your files.

Making sure that content is compatible across as many different devices and platforms as possible is crucial for any platform hosting media online. Transcoding allows you to convert media files into a myriad of formats, ensuring compatibility no matter what format the media was first uploaded in, and no matter what device your user is using.

Moreover, if you're looking to use adaptive streaming formats like HLS or DASH, transcoding your files is an imperative step in the adaptive streaming pipeline. Users nowadays expect to be able to continue playback even on a poor connection, which simply isn't possible with non-adaptive formats.

Perhaps one of the most important reasons for transcoding your files, though, is file optimization. Storage can be really costly, especially when dealing with large numbers of files. Instead of digging deep into your pockets, you can adjust the resolution, bitrate, and codec parameters, resulting in minimal quality loss, while reducing the amount of storage needed for your files.

Transcoding vs encoding

Transcoding and encoding are two terms that are often used interchangeably, but they actually refer to separate processes with subtle differences. Encoding is the process of converting data from one format to another. Typically, this is done to compress the data or to change it to a format that is more suitable for the desired application, such as streaming over the internet.

Transcoding, as already mentioned earlier, involves decoding the file into an intermediary format, and then encoding it into the target format. This is done to change the format or codec of the media file to ensure compatibility across devices or platforms, allowing you to ensure the best viewing experience regardless of the specifics of where the user is consuming your content.

How can I transcode videos with Transloadit?

Of course, you could set up an in-house transcoding pipeline, using CLI tools such as FFmpeg. However, integrating this into your media workflow can quickly blow up in scope, taking your focus away from your core product. Luckily, Transloadit offers an easy solution. Simply pass us your files, and our dedicated team of Robots will transform them to your exact specification. Then, the baton is passed back to you, to seamlessly deliver the content to your users.

How about we take a look at an example? The Template below shows how to make any uploaded video compatible for browsers, using Uppy.

{
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "browser720_webm_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "result": true,
      "ffmpeg_stack": "v6.0.0",
      "preset": "webm",
      "width": 1280,
      "height": 720,
      "turbo": false
    },
    "browser720_h264_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "result": true,
      "ffmpeg_stack": "v6.0.0",
      "preset": "ipad-high",
      "width": 1280,
      "height": 720,
      "turbo": false
    },
    "thumbed": {
      "use": "browser720_h264_encoded",
      "robot": "/video/thumbs",
      "result": true,
      "width": 1280,
      "height": 720,
      "format": "jpg",
      "resize_strategy": "fit",
      "count": 1,
      "ffmpeg_stack": "v6.0.0"
    },
    "exported": {
      "use": ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],
      "robot": "/s3/store",
      "credentials": "YOUR_AWS_CREDENTIALS",
      "url_prefix": "https://demos.transloadit.com/"
    }
  }
}
# Prerequisites: brew install curl jq || sudo apt install curl jq
# To avoid tampering, use Signature Authentication
echo '{
  "template_id": undefined,
  "auth": {
    "key": "YOUR_TRANSLOADIT_KEY"
  },
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "browser720_webm_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "result": true,
      "ffmpeg_stack": "v6.0.0",
      "preset": "webm",
      "width": 1280,
      "height": 720,
      "turbo": false
    },
    "browser720_h264_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "result": true,
      "ffmpeg_stack": "v6.0.0",
      "preset": "ipad-high",
      "width": 1280,
      "height": 720,
      "turbo": false
    },
    "thumbed": {
      "use": "browser720_h264_encoded",
      "robot": "/video/thumbs",
      "result": true,
      "width": 1280,
      "height": 720,
      "format": "jpg",
      "resize_strategy": "fit",
      "count": 1,
      "ffmpeg_stack": "v6.0.0"
    },
    "exported": {
      "use": ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],
      "robot": "/s3/store",
      "credentials": "YOUR_AWS_CREDENTIALS",
      "url_prefix": "https://demos.transloadit.com/"
    }
  }
}' | curl \
    --request POST \
    --form 'params=<-' \
    --form myfile1=@./surf.mp4 \
    https://api2.transloadit.com/assemblies | jq
// Install via Swift Package Manager:
// dependencies: [
//   .package(url: "https://github.com/transloadit/TransloaditKit", .upToNextMajor(from: "3.0.0"))
// ]

// Or via CocoaPods: // pod 'Transloadit', '~> 3.0.0'

// Auth let credentials = Credentials(key: "YOUR_TRANSLOADIT_KEY")

// Init let transloadit = Transloadit(credentials: credentials, session: "URLSession.shared")

// Add files to upload let filesToUpload: [URL] = ...

// Execute let assembly = transloadit.assembly(steps: [_originalStep, browser720_webm_encodedStep, browser720_h264_encodedStep, thumbedStep, exportedStep], andUpload: filesToUpload) { result in   switch result {   case .success(let assembly):     print("Retrieved (assembly)")   case .failure(let error):     print("Assembly error (error)")   } }.pollAssemblyStatus { result in   switch result {   case .success(let assemblyStatus):     print("Received assemblystatus (assemblyStatus)")   case .failure(let error):     print("Caught polling error (error)")   }

<!-- This pulls Uppy from our CDN -->
<!-- For smaller self-hosted bundles, install Uppy and plugins manually: -->
<!-- npm i --save @uppy/core @uppy/dashboard @uppy/remote-sources @uppy/transloadit ... -->
<link
  href="https://releases.transloadit.com/uppy/v4.3.0/uppy.min.css"
  rel="stylesheet"
/>
<button id="browse">Select Files</button>
<script type="module">
  import {
    Uppy,
    Dashboard,
    ImageEditor,
    RemoteSources,
    Transloadit,
  } from 'https://releases.transloadit.com/uppy/v4.3.0/uppy.min.mjs'
  const uppy = new Uppy()
    .use(Transloadit, {
      waitForEncoding: true,
      alwaysRunAssembly: true,
      assemblyOptions: {
        params: {
          // To avoid tampering, use Signature Authentication:
          // https://transloadit.com/docs/topics/signature-authentication/
          auth: {
            key: 'YOUR_TRANSLOADIT_KEY',
          },
          // It's often better store encoding instructions in your account
          // and use a template_id instead of adding these steps inline
          steps: {
            ':original': {
              robot: '/upload/handle',
            },
            browser720_webm_encoded: {
              use: ':original',
              robot: '/video/encode',
              result: true,
              ffmpeg_stack: 'v6.0.0',
              preset: 'webm',
              width: 1280,
              height: 720,
              turbo: false,
            },
            browser720_h264_encoded: {
              use: ':original',
              robot: '/video/encode',
              result: true,
              ffmpeg_stack: 'v6.0.0',
              preset: 'ipad-high',
              width: 1280,
              height: 720,
              turbo: false,
            },
            thumbed: {
              use: 'browser720_h264_encoded',
              robot: '/video/thumbs',
              result: true,
              width: 1280,
              height: 720,
              format: 'jpg',
              resize_strategy: 'fit',
              count: 1,
              ffmpeg_stack: 'v6.0.0',
            },
            exported: {
              use: ['browser720_webm_encoded', 'browser720_h264_encoded', 'thumbed', ':original'],
              robot: '/s3/store',
              credentials: 'YOUR_AWS_CREDENTIALS',
              url_prefix: 'https://demos.transloadit.com/',
            },
          },
        },
      },
    })
    .use(Dashboard, { trigger: '#browse' })
    .use(ImageEditor, { target: Dashboard })
    .use(RemoteSources, {
      companionUrl: 'https://api2.transloadit.com/companion',
    })
    .on('complete', ({ transloadit }) => {
      // Due to waitForEncoding:true this is fired after encoding is done.
      // Alternatively, set waitForEncoding to false and provide a notify_url
      console.log(transloadit) // Array of Assembly Statuses
      transloadit.forEach((assembly) => {
        console.log(assembly.results) // Array of all encoding results
      })
    })
    .on('error', (error) => {
      console.error(error)
    })
</script>
// yarn add transloadit || npm i transloadit

// Import const Transloadit = require('transloadit')

const main = async () => {   // Init   const transloadit = new Transloadit({     authKey: 'YOUR_TRANSLOADIT_KEY',     authSecret: 'MY_TRANSLOADIT_SECRET',   })

// Set Encoding Instructions   const options = {     files: {       myfile_1: './surf.mp4',     },     params: {       steps: {         ':original': {           robot: '/upload/handle',         },         browser720_webm_encoded: {           use: ':original',           robot: '/video/encode',           result: true,           ffmpeg_stack: 'v6.0.0',           preset: 'webm',           width: 1280,           height: 720,           turbo: false,         },         browser720_h264_encoded: {           use: ':original',           robot: '/video/encode',           result: true,           ffmpeg_stack: 'v6.0.0',           preset: 'ipad-high',           width: 1280,           height: 720,           turbo: false,         },         thumbed: {           use: 'browser720_h264_encoded',           robot: '/video/thumbs',           result: true,           width: 1280,           height: 720,           format: 'jpg',           resize_strategy: 'fit',           count: 1,           ffmpeg_stack: 'v6.0.0',         },         exported: {           use: ['browser720_webm_encoded', 'browser720_h264_encoded', 'thumbed', ':original'],           robot: '/s3/store',           credentials: 'YOUR_AWS_CREDENTIALS',           url_prefix: 'https://demos.transloadit.com/',         },       },     },   }

// Execute   const result = await transloadit.createAssembly(options)

// Show results   console.log({ result }) }

main().catch(console.error)

# [sudo] npm install transloadify -g

# Auth export TRANSLOADIT_KEY="YOUR_TRANSLOADIT_KEY"

# Save Encoding Instructions echo '{   "steps": {     ":original": {       "robot": "/upload/handle"     },     "browser720_webm_encoded": {       "use": ":original",       "robot": "/video/encode",       "result": true,       "ffmpeg_stack": "v6.0.0",       "preset": "webm",       "width": 1280,       "height": 720,       "turbo": false     },     "browser720_h264_encoded": {       "use": ":original",       "robot": "/video/encode",       "result": true,       "ffmpeg_stack": "v6.0.0",       "preset": "ipad-high",       "width": 1280,       "height": 720,       "turbo": false     },     "thumbed": {       "use": "browser720_h264_encoded",       "robot": "/video/thumbs",       "result": true,       "width": 1280,       "height": 720,       "format": "jpg",       "resize_strategy": "fit",       "count": 1,       "ffmpeg_stack": "v6.0.0"     },     "exported": {       "use": ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],       "robot": "/s3/store",       "credentials": "YOUR_AWS_CREDENTIALS",       "url_prefix": "https://demos.transloadit.com/"     }   } }' > ./steps.json

# Execute transloadify 
  --input "surf.mp4" 
  --steps "./steps.json" 
  --output "./output.example"

// composer require transloadit/php-sdk
use transloadit\Transloadit;

$transloadit = new Transloadit([   "key" => "YOUR_TRANSLOADIT_KEY",   "secret" => "MY_TRANSLOADIT_SECRET", ]);

// Start the Assembly $response = $transloadit->createAssembly([   "files" => ["surf.mp4"],   "params" => [     "steps" => [       ":original" => [         "robot" => "/upload/handle",       ],       "browser720_webm_encoded" => [         "use" => ":original",         "robot" => "/video/encode",         "result" => true,         "ffmpeg_stack" => "v6.0.0",         "preset" => "webm",         "width" => 1280,         "height" => 720,         "turbo" => false,       ],       "browser720_h264_encoded" => [         "use" => ":original",         "robot" => "/video/encode",         "result" => true,         "ffmpeg_stack" => "v6.0.0",         "preset" => "ipad-high",         "width" => 1280,         "height" => 720,         "turbo" => false,       ],       "thumbed" => [         "use" => "browser720_h264_encoded",         "robot" => "/video/thumbs",         "result" => true,         "width" => 1280,         "height" => 720,         "format" => "jpg",         "resize_strategy" => "fit",         "count" => 1,         "ffmpeg_stack" => "v6.0.0",       ],       "exported" => [         "use" => ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],         "robot" => "/s3/store",         "credentials" => "YOUR_AWS_CREDENTIALS",         "url_prefix" => "https://demos.transloadit.com/",       ],     ],   ], ]);

# gem install transloadit

# $ irb -rubygems # >> require 'transloadit' # => true

transloadit = Transloadit.new([   :key => "YOUR_TRANSLOADIT_KEY", ])

# Set Encoding Instructions _original = transloadit.step(":original", "/upload/handle", {})

browser720_webm_encoded = transloadit.step("browser720_webm_encoded", "/video/encode", [   :use => ":original",   :result => true,   :ffmpeg_stack => "v6.0.0",   :preset => "webm",   :width => 1280,   :height => 720,   :turbo => false ])

browser720_h264_encoded = transloadit.step("browser720_h264_encoded", "/video/encode", [   :use => ":original",   :result => true,   :ffmpeg_stack => "v6.0.0",   :preset => "ipad-high",   :width => 1280,   :height => 720,   :turbo => false ])

thumbed = transloadit.step("thumbed", "/video/thumbs", [   :use => "browser720_h264_encoded",   :result => true,   :width => 1280,   :height => 720,   :format => "jpg",   :resize_strategy => "fit",   :count => 1,   :ffmpeg_stack => "v6.0.0" ])

exported = transloadit.step("exported", "/s3/store", [   :use => ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],   :credentials => "YOUR_AWS_CREDENTIALS",   :url_prefix => "https://demos.transloadit.com/" ])

transloadit.assembly([   :steps => [_original, browser720_webm_encoded, browser720_h264_encoded, thumbed, exported] ])

# Add files to upload files = [] files.push("surf.mp4")

# Start the Assembly response = assembly.create! *files

until response.finished?   sleep 1; response.reload! end

if !response.error?   # handle success end

# pip install pytransloadit
from transloadit import client

tl = client.Transloadit('YOUR_TRANSLOADIT_KEY', 'MY_TRANSLOADIT_SECRET') assembly = tl.new_assembly()

# Set Encoding Instructions assembly.add_step(":original", "/upload/handle", {})

assembly.add_step("browser720_webm_encoded", "/video/encode", {   'use': ':original',   'result': True,   'ffmpeg_stack': 'v6.0.0',   'preset': 'webm',   'width': 1280,   'height': 720,   'turbo': False })

assembly.add_step("browser720_h264_encoded", "/video/encode", {   'use': ':original',   'result': True,   'ffmpeg_stack': 'v6.0.0',   'preset': 'ipad-high',   'width': 1280,   'height': 720,   'turbo': False })

assembly.add_step("thumbed", "/video/thumbs", {   'use': 'browser720_h264_encoded',   'result': True,   'width': 1280,   'height': 720,   'format': 'jpg',   'resize_strategy': 'fit',   'count': 1,   'ffmpeg_stack': 'v6.0.0' })

assembly.add_step("exported", "/s3/store", {   'use': ['browser720_webm_encoded', 'browser720_h264_encoded', 'thumbed', ':original'],   'credentials': 'YOUR_AWS_CREDENTIALS',   'url_prefix': 'https://demos.transloadit.com/' })

# Add files to upload assembly.add_file(open('surf.mp4', 'rb'))

# Start the Assembly assembly_response = assembly.create(retries=5, wait=True)

print(assembly_response.data.get('assembly_ssl_url')) # or: print(assembly_response.data['assembly_ssl_url'])

// go get gopkg.in/transloadit/go-sdk.v1
package main

import (   "context"   "fmt"   "github.com/transloadit/go-sdk" )

func main() {   // Create client   options := transloadit.DefaultConfig   options.AuthKey = "YOUR_TRANSLOADIT_KEY"   options.AuthSecret = "MY_TRANSLOADIT_SECRET"   client := transloadit.NewClient(options)      // Initialize new Assembly   assembly := transloadit.NewAssembly()      // Set Encoding Instructions   assembly.AddStep(":original", map[string]interface{}{     "robot": "/upload/handle",   })      assembly.AddStep("browser720_webm_encoded", map[string]interface{}{     "use": ":original",     "robot": "/video/encode",     "result": true,     "ffmpeg_stack": "v6.0.0",     "preset": "webm",     "width": 1280,     "height": 720,     "turbo": false,   })      assembly.AddStep("browser720_h264_encoded", map[string]interface{}{     "use": ":original",     "robot": "/video/encode",     "result": true,     "ffmpeg_stack": "v6.0.0",     "preset": "ipad-high",     "width": 1280,     "height": 720,     "turbo": false,   })      assembly.AddStep("thumbed", map[string]interface{}{     "use": "browser720_h264_encoded",     "robot": "/video/thumbs",     "result": true,     "width": 1280,     "height": 720,     "format": "jpg",     "resize_strategy": "fit",     "count": 1,     "ffmpeg_stack": "v6.0.0",   })      assembly.AddStep("exported", map[string]interface{}{     "use": ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],     "robot": "/s3/store",     "credentials": "YOUR_AWS_CREDENTIALS",     "url_prefix": "https://demos.transloadit.com/",   })      // Add files to upload   assembly.AddFile("surf.mp4"))      // Start the Assembly   info, err := client.StartAssembly(context.Background(), assembly)   if err != nil {     panic(err)   }      // All files have now been uploaded and the Assembly has started but no   // results are available yet since the conversion has not finished.   // WaitForAssembly provides functionality for polling until the Assembly   // has ended.   info, err = client.WaitForAssembly(context.Background(), info)   if err != nil {     panic(err)   }      fmt.Printf("You can check some results at: ")   fmt.Printf("  - %s\n", info.Results[":original"][0].SSLURL)   fmt.Printf("  - %s\n", info.Results["browser720_webm_encoded"][0].SSLURL)   fmt.Printf("  - %s\n", info.Results["browser720_h264_encoded"][0].SSLURL)   fmt.Printf("  - %s\n", info.Results["thumbed"][0].SSLURL)   fmt.Printf("  - %s\n", info.Results["exported"][0].SSLURL) }

// implementation 'com.transloadit.sdk:transloadit:1.0.0'

import com.transloadit.sdk.Assembly; import com.transloadit.sdk.Transloadit; import com.transloadit.sdk.exceptions.LocalOperationException; import com.transloadit.sdk.exceptions.RequestException; import com.transloadit.sdk.response.AssemblyResponse; import java.io.File; import java.util.HashMap; import java.util.Map;

public class Main {   public static void main(String[] args) {     // Initialize the Transloadit client     Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "MY_TRANSLOADIT_SECRET");          Assembly assembly = transloadit.newAssembly();          // Set Encoding Instructions     Map<String, Object> _originalStepOptions = new HashMap();     assembly.addStep(":original", "/upload/handle", _originalStepOptions);          Map<String, Object> browser720_webm_encodedStepOptions = new HashMap();     browser720_webm_encodedStepOptions.put("use", ":original");     browser720_webm_encodedStepOptions.put("result", true);     browser720_webm_encodedStepOptions.put("ffmpeg_stack", "v6.0.0");     browser720_webm_encodedStepOptions.put("preset", "webm");     browser720_webm_encodedStepOptions.put("width", 1280);     browser720_webm_encodedStepOptions.put("height", 720);     browser720_webm_encodedStepOptions.put("turbo", false);     assembly.addStep("browser720_webm_encoded", "/video/encode", browser720_webm_encodedStepOptions);          Map<String, Object> browser720_h264_encodedStepOptions = new HashMap();     browser720_h264_encodedStepOptions.put("use", ":original");     browser720_h264_encodedStepOptions.put("result", true);     browser720_h264_encodedStepOptions.put("ffmpeg_stack", "v6.0.0");     browser720_h264_encodedStepOptions.put("preset", "ipad-high");     browser720_h264_encodedStepOptions.put("width", 1280);     browser720_h264_encodedStepOptions.put("height", 720);     browser720_h264_encodedStepOptions.put("turbo", false);     assembly.addStep("browser720_h264_encoded", "/video/encode", browser720_h264_encodedStepOptions);          Map<String, Object> thumbedStepOptions = new HashMap();     thumbedStepOptions.put("use", "browser720_h264_encoded");     thumbedStepOptions.put("result", true);     thumbedStepOptions.put("width", 1280);     thumbedStepOptions.put("height", 720);     thumbedStepOptions.put("format", "jpg");     thumbedStepOptions.put("resize_strategy", "fit");     thumbedStepOptions.put("count", 1);     thumbedStepOptions.put("ffmpeg_stack", "v6.0.0");     assembly.addStep("thumbed", "/video/thumbs", thumbedStepOptions);          Map<String, Object> exportedStepOptions = new HashMap();     exportedStepOptions.put("use", new String[] { "browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original" });     exportedStepOptions.put("credentials", "YOUR_AWS_CREDENTIALS");     exportedStepOptions.put("url_prefix", "https://demos.transloadit.com/");     assembly.addStep("exported", "/s3/store", exportedStepOptions);          // Add files to upload     assembly.addFile(new File("surf.mp4"));          // Start the Assembly     try {       AssemblyResponse response = assembly.save();            // Wait for Assembly to finish executing       while (!response.isFinished()) {         response = transloadit.getAssemblyByUrl(response.getSslUrl());       }            System.out.println(response.getId());       System.out.println(response.getUrl());       System.out.println(response.json());     } catch (RequestException | LocalOperationException e) {       // Handle exception here     }   } }

And this is just the tip of the iceberg. We have a variety of others demos, just like the one above. We encourage you to take a look.

Next steps

Hopefully, you now have the knowledge necessary to become a legendary transcoding wizard 🧙 If so, embark on the next step in your journey and sign up for Transloadit below, with our free forever Community Plan. Our outstanding support team is happy to help you, in case you get stuck along the way.