GithubHelp home page GithubHelp logo

bannerbear-ruby's Introduction

Bannerbear Ruby

Ruby wrapper for the Bannerbear API - an image and video generation service.

Installation

Add this line to your application's Gemfile:

gem 'bannerbear'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install bannerbear

Usage

Table of Contents

Authentication

Get the API key for your project in Bannerbear and create a client.

bb = Bannerbear::Client.new("your API key")

Alternatively you can place your API key in an ENV variable named BANNERBEAR_API_KEY and create the client:

bb = Bannerbear::Client.new

Account Info

Return info about the Account / Project associated with this API key.

bb.account

Images

Create an Image

To create an image you reference a template uid and a list of modifications. The default is async generation meaning the API will respond with a pending status and you can use get_image to retrieve the final image.

bb.create_image("template uid", 
  :modifications => [
    {
      :name => "headline",
      :text => "Hello World!"
    },
    {
      :name => "photo",
      :image_url => "https://images.unsplash.com/photo-1555400038-63f5ba517a47?w=1000&q=80"
    }
  ]
)

You can also create images synchronously - this will take longer to respond but the image will be delivered in the response:

bb.create_image("template uid", 
  :synchronous => true, 
  :modifications => [
    {
      :name => "headline",
      :text => "Hello World!"
    },
    {
      :name => "photo",
      :image_url => "https://images.unsplash.com/photo-1555400038-63f5ba517a47?w=1000&q=80"
    }
  ]
)
Options
  • modifications: an array of modifications you would like to make (array)
  • webhook_url: a webhook url to post the final image object to (string)
  • transparent: render image with a transparent background (boolean)
  • synchronous: generate the image synchronously (boolean)
  • render_pdf: render a PDF in addition to an image (boolean)
  • metadata: include any metadata to reference at a later point (string)

Get an Image

bb.get_image("image uid")

List all Images

bb.list_images
bb.list_images(:page => 10)
Options
  • page: pagination (integer)
  • limit: return n images per page (integer)

Videos

Create a Video

To create a video you reference a video template uid, an input media and a list of modifications. Videos are created async - use get_video to retrieve the final video.

bb.create_video("video template uid", 
  :input_media_url => "https://www.yourserver.com/videos/awesome_video.mp4", 
  :modifications => [
    {
      :name => "headline",
      :text => "Hello World!"
    }
  ]
)
Options
  • input_media_url: a url to a publicly available video file you want to import (string)
  • modifications: an array of modifications you would like to make to the video overlay (array)
  • webhook_url: a webhook url to post the final video object to (string)
  • blur: blur the imported video from 1-10 (integer)
  • trim_to_length_in_seconds: trim the video to a specific length (integer)
  • create_gif_preview: create a short preview gif (boolean)
  • metadata: include any metadata to reference at a later point (string)

If your video is using the "Multi Overlay" build pack then you can pass in a set of frames to render via:

  • frames: an array of sets of modifications (array)
  • frame_durations: specify the duration of each frame (array)

Get a Video

bb.get_video("video uid")

Update a Video

Updating a video is only relevant under specific conditions. Video Templates using the build pack transcribe and set to manual approval (via the dashboard) will result in videos that enter a pending_approval status. At this point, the video is waiting for approval before final rendering. The purpose of this is to check the transcript is correct, make any changes, and approve the video for rendering.

bb.update_video("video uid",
  :approved => true,
  :transcription => [
    "This is a new transcription",
    "It must contain the same number of lines",
    "As the previous transcription"
  ]
)
Options
  • approved: approve the video for rendering (boolean)
  • transcription: an array of strings to represent the new transcription (will overwrite the existing one) (array)

List all Videos

bb.list_videos
Options
  • page: pagination (integer)

Collections

Create multiple images in one API request.

bb.get_collection("collection uid")
bb.list_collections(:page => 3)
bb.create_collection("template set uid",
  :synchronous => true,
  :modifications => [
    {
      :name => "headline",
      :text => "Hello World!"
    }
  ]
) 
Options for create_collection
  • modifications: an array of modifications you would like to make (array)
  • webhook_url: a webhook url to post the final collection object to (string)
  • transparent: render image with a transparent background (boolean)
  • synchronous: generate the images synchronously (boolean)
  • metadata: include any metadata to reference at a later point (string)

Animated Gifs

Create a slideshow style gif

bb.get_animated_gif("gif uid")
bb.list_animated_gifs(:page => 3)
bb.create_animated_gif("template uid",
  :frames => [
    [ #frame 1 starts here
      {
        :name => "layer1",
        :text => "This is my text"
      },
      {
        :name => "photo",
        :image_url => "https://www.pathtomyphoto.com/1.jpg"
      }
    ],
    [ #frame 2 starts here
      {
        :name => "layer1",
        :text => "This is my follow up text"
      },
      {
        :name => "photo",
        :image_url => "https://www.pathtomyphoto.com/2.jpg"
      }
    ]
  ]
) 
Options for create_animated_gif
  • frames: an array of arrays of modifications you would like to make (array)
  • frame_durations: an array of times (in seconds) to show each frame (array)
  • input_media_url: optionally import an external video file to use as part of the gif
  • fps: frames per second e.g. 1 (integer)
  • loop: whether to loop or not (boolean)
  • webhook_url: a webhook url to post the final gif object to (string)
  • metadata: include any metadata to reference at a later point (string)

Movies

Assemble video clips or still images into a single movie with transitions.

bb.get_movie("movie uid")
bb.list_movies(:page => 3)
bb.create_movie(:width => 800, :height => 800, :transition => "pixelize", :inputs => [
  {
    :asset_url => "https://images.unsplash.com/photo-1635910160061-4b688344bd20?w=500&q=60"
  },
  {
    :asset_url => "https://i.imgur.com/fH7a5dO.png"
  }
])
Options for create_movie
  • width: the movie width in pixels (integer)
  • height: the movie height in pixels (integer)
  • transition: the transition style: fade, pixelize, slidedown, slideright, slideup, slideleft (string)
  • inputs: a list of inputs (array)
  • webhook_url: a webhook url to post the final movie object to (string)
  • metadata: include any metadata to reference at a later point (string)

Screenshots

Take screenshots of websites.

bb.get_screenshot("screenshot uid")
bb.list_screenshots(:page => 3)
bb.create_screenshot("https://www.bannerbear.com/",
  :synchronous => true,
  :width => 1000
) 
Options for create_screenshot
  • width: the desired screenshot width in pixels (integer)
  • height: the desired screenshot height in pixels (integer)
  • synchronous: generate the screenshot synchronously (boolean)
  • mobile: use a mobile user agent
  • webhook_url: a webhook url to post the final screenshot object to (string)

Templates

bb.get_template("template uid")
bb.update_template("template uid", :name => "New Template Name", :tags => ["portrait", "instagram"])
bb.list_templates(:page => 2, :tag => "portrait")

Template Sets

bb.get_template_set("template set uid")
bb.list_template_sets(:page => 2)

Video Templates

bb.get_video_template("video template uid")
bb.list_video_templates(:page => 2)

Signed URLs

This gem also includes a convenient utility for generating signed urls. Authenticate as above, then:

bb.generate_signed_url("base uid", :modifications => [])

# example
bb.generate_signed_url("A89wavQyY3Bebk3djP", 
  :modifications => [
    {
      :name => "country", 
      :text => "testing!"
    },
    {
      :name => "photo", 
      :image_url => "https://images.unsplash.com/photo-1638356435991-4c79b00ebef3?w=764&q=80"
    }
  ]
)
# https://ondemand.bannerbear.com/signedurl/A89wavQyY3Bebk3djP/image.jpg?modifications=W3sibmFtZSI6ImNvdW50cnkiLCJ0ZXh0IjoidGVzdGluZyEifSx7Im5hbWUiOiJwaG90byIsImltYWdlX3VybCI6Imh0dHBzOi8vaW1hZ2VzLnVuc3BsYXNoLmNvbS9waG90by0xNjM4MzU2NDM1OTkxLTRjNzliMDBlYmVmMz93PTc2NCZxPTgwIn1d&s=40e7c9d4902b86ea83e0c400e57d7cc580534fd527e234d40a0c7ace589a16eb

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/yongfook/bannerbear-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Bannerbear project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

bannerbear-ruby's People

Contributors

sprad avatar yongfook avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

khaledrepos sprad

bannerbear-ruby's Issues

Handle rate limiting internally

What happens:

When calling create_image() too frequently (more than 30 times in 10 seconds), it throws a JSON parse exception from deep inside the gem that contains a Cloudflare html response:

Traceback (most recent call last):
...local paths redacted...
         3: from .rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/bannerbear-0.1.4/lib/bannerbear/client.rb:3
2:in `create_image'
         2: from .rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/bannerbear-0.1.4/lib/bannerbear/client.rb:1
95:in `post_response'
         1: from .rbenv/versions/2.7.6/lib/ruby/2.7.0/json/common.rb:156:in `parse'
.rbenv/versions/2.7.6/lib/ruby/2.7.0/json/common.rb:156:in `parse': 783: unexpected token at '<!DOCTYPE html> (JSON::ParserError)
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
<head>
<title>Access denied | api.bannerbear.com used Cloudflare to restrict access</title>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/main.css" />


<script>
(function(){if(document.addEventListener&&window.XMLHttpRequest&&JSON&&JSON.stringify){var e=function(a){var c=document.getEle
mentById("error-feedback-survey"),d=document.getElementById("error-feedback-success"),b=new XMLHttpRequest;a={event:"feedback 
clicked",properties:{errorCode:1015,helpful:a,version:1}};b.open("POST","https://sparrow.cloudflare.com/api/v1/event");b.setRe
questHeader("Content-Type","application/json");b.setRequestHeader("Sparrow-Source-Key","c771f0e4b54944bebf4261d44bd79a1e");
b.send(JSON.stringify(a));c.classList.add("feedback-hidden");d.classList.remove("feedback-hidden")};document.addEventListener(
"DOMContentLoaded",function(){var a=document.getElementById("error-feedback"),c=document.getElementById("feedback-button-yes")
,d=document.getElementById("feedback-button-no");"classList"in a&&(a.classList.remove("feedback-hidden"),c.addEventListener("c
lick",function(){e(!0)}),d.addEventListener("click",function(){e(!1)}))})}})();
</script>

<script defer src="https://performance.radar.cloudflare.com/beacon.js"></script>
</head>
<body>
  <div id="cf-wrapper">
    <div class="cf-alert cf-alert-error cf-cookie-error hidden" id="cookie-alert" data-translate="enable_cookies">Please enabl
e cookies.</div>
    <div id="cf-error-details" class="p-0">
      <header class="mx-auto pt-10 lg:pt-6 lg:px-8 w-240 lg:w-full mb-15 antialiased">
         <h1 class="inline-block md:block mr-2 md:mb-2 font-light text-60 md:text-3xl text-black-dark leading-tight">
           <span data-translate="error">Error</span>
           <span>1015</span>
         </h1>
         <span class="inline-block md:block heading-ray-id font-mono text-15 lg:text-sm lg:leading-relaxed">Ray ID: 85934ffe8e
87091c &bull;</span>
         <span class="inline-block md:block heading-ray-id font-mono text-15 lg:text-sm lg:leading-relaxed">2024-02-22 01:03:5
9 UTC</span>
        <h2 class="text-gray-600 leading-1.3 text-3xl lg:text-2xl font-light">You are being rate limited</h2>
      </header>

      <section class="w-240 lg:w-full mx-auto mb-8 lg:px-8">
          <div id="what-happened-section" class="w-1/2 md:w-full">
            <h2 class="text-3xl leading-tight font-normal mb-4 text-black-dark antialiased" data-translate="what_happened">Wha
t happened?</h2>
            <p>The owner of this website (api.bannerbear.com) has banned you temporarily from accessing this website.</p>
            
          </div>

          
      </section>

      <div class="feedback-hidden py-8 text-center" id="error-feedback">
    <div id="error-feedback-survey" class="footer-line-wrapper">
        Was this page helpful?
        <button class="border border-solid bg-white cf-button cursor-pointer ml-4 px-4 py-2 rounded" id="feedback-button-yes" 
type="button">Yes</button>
        <button class="border border-solid bg-white cf-button cursor-pointer ml-4 px-4 py-2 rounded" id="feedback-button-no" t
ype="button">No</button>
    </div>
    <div class="feedback-success feedback-hidden" id="error-feedback-success">
        Thank you for your feedback!
    </div>
</div>


      <div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-sol
id border-0 border-t border-gray-300">
  <p class="text-13">
    <span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">85934ffe8e87091c</strong></
span>
    <span class="cf-footer-separator sm:hidden">&bull;</span>
    <span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
      Your IP:
      <button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
      <span class="hidden" id="cf-footer-ip">2600:1700:2d25:81e0:cd59:5204:9587:9f49</span>
      <span class="cf-footer-separator sm:hidden">&bull;</span>
    </span>
    <span class="cf-footer-item sm:block sm:mb-1"><span>Performance &amp; security by</span> <a rel="noopener noreferrer" href
="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
    
  </p>
  <script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"c
lassList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById(
"cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",
d)})();</script>
</div><!-- /.error-footer -->


    </div><!-- /#cf-error-details -->
  </div><!-- /#cf-wrapper -->

  <script>
  window._cf_translation = {};
  
  
</script>

</body>
</html>
'

What I expected:

I expected the client library to recognize the retryable 429 response code and take care of pauses and retries as needed.

Or, less ideal, but better: I'd expect to get a JSON response that's parsed correctly by the library instead of an exception.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.