Video stabilization robot

Archived from the Transloadit support forum. Originally posted on December 31, 2013; details may be outdated, see our docs for current behavior. Original thread

Video stabilization robot would be awesome! :slight_smile:
or, generally, a post-video processing robot that can do more than just watermark. Thank you!

Hey Sergey,

thank you for the suggestion! What would it be able to do exactly, especially concerning “stabilization”?

Kind regards,
Tim

Hi Sergey,

Although we don’t have an abstraction for stabilization, through the customization of ffmpeg options we let customers set filters themselves. This way you could for instance say:

ffmpeg_stack: "v2.0.0",
ffmpeg: {
 vf: "deshake"
}

Let me know if that helps,

Kind regards,
Kevin

It works great! I can see noticeable difference. You can check this assembly for results:

https://transloadit.com/templates/result/REDACTED

One question though, what would be the overhead of deshake compared to transcode? It is ok to have deshake filter as part of transcode, or should I create a separate step that would do deshake once per video?

Here is my complete template for reference if anyone needs it:

{
  "steps": {
    "files": {
      "robot": "/file/filter",
      "accepts": [
        [
          "${file.mime}",
          "regex",
          "image"
        ],
        [
          "${file.mime}",
          "regex",
          "video"
        ]
      ],
      "error_on_decline": true
    },
    "iphone": {
      "use": ":original",
      "robot": "/video/encode",
      "ffmpeg_stack": "v2.0.0",
      "preset": "iphone",
      "ffmpeg": {
        "vf": "deshake"
      }
    },
    "iphone-preview": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "iphone-low",
      "ffmpeg_stack": "v2.0.0",
      "ffmpeg": {
        "t": 10
      }
    },
    "ipad": {
      "use": ":original",
      "robot": "/video/encode",
      "ffmpeg_stack": "v2.0.0",
      "preset": "ipad",
      "ffmpeg": {
        "vf": "deshake"
      }
    },
    "ipad-preview": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "ipad-low",
      "ffmpeg_stack": "v2.0.0",
      "ffmpeg": {
        "t": 10
      }
    },
    "flash": {
      "use": ":original",
      "robot": "/video/encode",
      "ffmpeg_stack": "v2.0.0",
      "preset": "flash",
      "ffmpeg": {
        "vf": "deshake"
      }
    },
    "flash-preview": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "flash",
      "ffmpeg_stack": "v2.0.0",
      "ffmpeg": {
        "t": 10
      }
    },
    "webm": {
      "use": ":original",
      "robot": "/video/encode",
      "ffmpeg_stack": "v2.0.0",
      "preset": "webm",
      "ffmpeg": {
        "vf": "deshake"
      }
    },
    "webm-preview": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "webm",
      "ffmpeg_stack": "v2.0.0",
      "ffmpeg": {
        "t": 10
      }
    },
    "android": {
      "use": ":original",
      "robot": "/video/encode",
      "ffmpeg_stack": "v2.0.0",
      "preset": "android",
      "ffmpeg": {
        "vf": "deshake"
      }
    },
    "android-preview": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "android-low",
      "ffmpeg_stack": "v2.0.0",
      "ffmpeg": {
        "t": 10
      }
    },
    "video-thumbnails-s": {
      "use": ":original",
      "robot": "/video/thumbs",
      "resize_strategy": "fit",
      "format": "jpg",
      "offsets": [
        "2%",
        "10%",
        "20%",
        "30%",
        "40%",
        "50%",
        "60%",
        "70%",
        "80%",
        "98%"
      ],
      "width": 480,
      "height": 320,
      "count": 10
    },
    "video-thumbnails-m": {
      "use": ":original",
      "robot": "/video/thumbs",
      "resize_strategy": "fit",
      "format": "jpg",
      "offsets": [
        "2%",
        "10%",
        "20%",
        "30%",
        "40%",
        "50%",
        "60%",
        "70%",
        "80%",
        "98%"
      ],
      "width": 640,
      "height": 480,
      "count": 10
    },
    "video-thumbnails-l": {
      "use": ":original",
      "robot": "/video/thumbs",
      "resize_strategy": "fit",
      "format": "jpg",
      "offsets": [
        "2%",
        "10%",
        "20%",
        "30%",
        "40%",
        "50%",
        "60%",
        "70%",
        "80%",
        "98%"
      ],
      "width": 800,
      "height": 600,
      "count": 10
    },
    "image-thumbnail-s": {
      "robot": "/image/resize",
      "use": ":original",
      "width": 480,
      "height": 320,
      "quality": 40,
      "resize_strategy": "fillcrop",
      "format": "jpg",
      "strip": true
    },
    "image-thumbnail-m": {
      "robot": "/image/resize",
      "use": ":original",
      "width": 640,
      "height": 480,
      "quality": 80,
      "resize_strategy": "fillcrop",
      "format": "jpg",
      "strip": true
    },
    "image-thumbnail-l": {
      "robot": "/image/resize",
      "use": ":original",
      "width": 800,
      "height": 600,
      "quality": 90,
      "resize_strategy": "fit",
      "format": "jpg",
      "strip": true
    },
    "export-original": {
      "use": [
        ":original"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/original.${file.ext}"
    },
    "export-video-thumbnails-s": {
      "use": [
        "video-thumbnails-s"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-s-${file.meta.thumb_index}.${file.ext}"
    },
    "export-video-thumbnails-m": {
      "use": [
        "video-thumbnails-m"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-m-${file.meta.thumb_index}.${file.ext}"
    },
    "export-video-thumbnails-l": {
      "use": [
        "video-thumbnails-m"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-l-${file.meta.thumb_index}.${file.ext}"
    },
    "export-image-thumbnail-s": {
      "use": [
        "image-thumbnail-s"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-s-0.${file.ext}"
    },
    "export-image-thumbnail-m": {
      "use": [
        "image-thumbnail-m"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-m-0.${file.ext}"
    },
    "export-image-thumbnail-l": {
      "use": [
        "image-thumbnail-l"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/thumb-l-0.${file.ext}"
    },
    "export-previews": {
      "use": [
        "flash-preview",
        "ipad-preview",
        "iphone-preview",
        "android-preview",
        "webm-preview"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/${previous_step.name}.${file.ext}"
    },
    "export-videos": {
      "use": [
        "flash",
        "ipad",
        "iphone",
        "android",
        "webm"
      ],
      "robot": "/s3/store",
      "key": "REDACTED",
      "secret": "REDACTED",
      "bucket": "content-dev",
      "path": "user-${fields.createdby}/${assembly.id}/${previous_step.name}.${file.ext}"
    }
  }
}

Hey Sergey,

Awesome to hear it works!

About the overhead, let us worry about cputime & scaling. We encourage customers to get the most out of their GBs as long as they’re not intentionally giving us hard times without producing anything significant to show for it : )
This is well within boundaries ; )

Enjoy deshaked videos! In fact, I think maybe we should do a blog post as I don’t think many customers know they can do this.

Do you have an implementation online that would be cool to link in that?

Kind regards,
Kevin

Closing this. If you have more questions, please reply to this ticket which will re-open it.

Kind regards,
Tim

Co-Founder Transloadit
@tim_kos