Perl HTTP::Tiny: submit a MiniMax H3 video job and save it

A 23-line Perl script with core modules only: POST /v1/videos for minimax-h3, poll, download. A 5-second 768p clip is $0.375; 480p is $0.3125.

4 min readSume
All posts

Perl still runs a lot of build glue, report generators and cron scripts, and none of it needs a video SDK. HTTP::Tiny and JSON::PP ship with Perl, and that is all the Sume video API needs: one POST, a poll loop and a GET for the finished file.

This post is the full script for MiniMax H3 (minimax-h3). It ran against a local stand-in server that returns the documented 202, poll and 302 shapes; the live service decides real render times. The script is 23 lines and uses HTTP::Tiny 0.076.

The script

Export SUME_API_KEY and run perl video.pl. The clip is 5 seconds at 768p, 16:9. 768p is H3's native size, so do not request 720p; the API would reject it.

use strict; use warnings;
use HTTP::Tiny; use JSON::PP qw(encode_json decode_json);
my $base = $ENV{SUME_API_BASE} // 'https://api.sume.com';
my $key  = $ENV{SUME_API_KEY} // die "set SUME_API_KEY\n";
my $http = HTTP::Tiny->new(default_headers => { Authorization => "Bearer $key" });
my $res = $http->post("$base/v1/videos", {
    headers => { 'Content-Type' => 'application/json', 'Idempotency-Key' => 'perl-h3-0001' },
    content => encode_json({ model => 'minimax-h3', prompt => 'A koi pond at dawn',
        duration => 5, resolution => '768p', aspect_ratio => '16:9' }),
});
die "submit failed: $res->{status} $res->{content}\n" unless $res->{status} == 202;
my $poll = decode_json($res->{content})->{polling_url};
while (1) {
    sleep($ENV{POLL_SECONDS} // 30);
    my $job = decode_json($http->get($poll)->{content});
    die "$job->{status}\n" if $job->{status} =~ /^(failed|cancelled)$/;
    next unless $job->{status} eq 'completed';
    my $file = $http->get($job->{unsigned_urls}[0]);   # HTTP::Tiny follows the 302
    die "download failed: $file->{status}\n" unless $file->{success};
    open my $fh, '>:raw', 'out.mp4' or die $!;
    print $fh $file->{content}; close $fh;
    print "cost $job->{usage}{cost}\n"; last;
}

Notes on the code

Perl details first, then the API details.

  • HTTP::Tiny follows redirects for GET by default, so the content URL's 302 needs no handling. The script checks $file->{success} so an error body is not written into out.mp4.
  • The status check dies on failed and cancelled. A Perl last leaves the loop once completed is saved.
  • Idempotency-Key makes a retried POST return the original job. Pick one key per clip you mean to create.
  • H3 always has native stereo audio, so the script does not send generate_audio.

What it costs

MiniMax H3 is priced per second by resolution. Sume's price is the provider list rate times 1.25. The native sizes are 480p and 768p; 2K and 4K are paid upscales of the 768p picture, and text-to-video accepts 5 to 15 seconds.

MiniMax H3 native-resolution price on Sume (pricing tables, read 2026-10-05)
ResolutionPer second5 s clip15 s clip
480p$0.0625$0.3125$0.9375
768p$0.075$0.375$1.125

References have a fee

Reference-to-video takes up to 9 images, 3 videos and 3 audio files, 12 in total. The first five reference images are free; each one after that adds $0.10 on Sume, which is the $0.08 list fee times 1.25. Plan a character sheet with five images or fewer if you want the per-second price to be the whole price. A 5-second 768p clip with seven reference images, for example, is $0.375 for the seconds plus two extra images at $0.10, which comes to $0.575. Checking that sum before you submit is cheap, and the reserve at submit is computed the same way, so an unexpectedly high reserve is a hint that you attached more images than you meant to.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume