Bepasty image uploader

For many years I used bepasty-client-cli to upload my screenshots via script to my paste-bin: bepasty-server. Somehow broke the bepasty-cli a few days ago and I don't want to invest time in an unmaintained cli client.

First I tried to solve the upload by only using curl and base64. But actually figuring out what to set for Content-Length and Content-Range with only getting 400 errors from bepasty-server was so annoying, that I canceled my solution attempt.

My working solution ( borrowed as little code as possible from bepasty-cli:

import base64
import sys
import click
import requests

@click.option("-u", "--url")
@click.option("-p", "--password")
@click.option("-f", "--filename")
def main(url, password, filename):
    with open(filename, "rb") as fp:
        raw_data =
        payload = base64.b64encode(raw_data)
        raw_data_size = len(raw_data)
        filesize = raw_data_size

        headers = {
            "Content-Range": "bytes %d-%d/%d" % (0, 0 + raw_data_size - 1, filesize),
            "Content-Type": "image/png",
            "Content-Filename": "screen.png",
            "Content-Length": str(len(payload)),
            "Maxlife-Unit": "FOREVER",
            "Maxlife-Value": "1",

        r =
            auth=("user", password),
        if r.status_code == 201:
            loc = r.headers["Content-Location"].split("/")[-1]

if __name__ == "__main__":
This code doesn't support chunked uploads. For image files this should never be a problem to always upload the whole file.
Printing the url with the filename is important, because in the script this is called the url is automatically opened via xdg-open.

My looks like this:


old=$(xsel -o -b)
sleep 0.1
f=$(scrot -s -e 'echo $f')
result=$(python ~/bin/ -p PASSWORD -u https://some-paste-bin-url.example -f $f)
if [ "$?" -ne "0" ]; then
    echo $result; exit 1
echo $result | head -n 1 | xsel -i -b
url=$(xsel -o -b)
if [ "$old" != "$url" ]; then
    xdg-open $url
rm $f


Having my own ActivityPub instance to experiment with sounded like a good idea.
To reduce time consuming maintenance I decided to try running on

The setup currently running on is public on github:

Some context to the setup/config:
  • For persistence between deployments a volume is needed. 1GB is the minimal size and should be enough for quite a while.

  • I disabled public registration, so registration has to happen via flyctl ssh console.

  • To not have the hassle with setting up email, I disabled it.

  • Updating should be easy by changing the version in, run it, and deploy again. Time will tell if this is the case.

  • The smallest instance size available (shared-cpu-1x 256MB) seems to be enough:

load and memory of fly instance

If I missed something or any questions arise, feel free to message me on

ffmpeg - images to videos and vice versa

To get training material for an image classifier I recorded a few videos with my GoPro and converted them later to images using ffmpeg.

My example usage here:

ffmpeg -i GOPR0001.MP4 -s 1280x720 -vf fps=10 images/G01%04d_720p.png

The 4k MP4-video is converted to 720p with 10 png images per second. A frame number is added to the image name with %04d.

After written some Python-opencv code to generate data for training I wanted to have a preview video to show my collaborators. So the other way around: a lot of images converted to a video.

cat images/* | ffmpeg -f image2pipe -framerate 5 -i - -f webm -vcodec libvpx-vp9 video.webm

The images are piped to ffmpeg and a webm(vp9) video is generated with a framerate of 5 images per second.

I experimented a bit with codecs but I found none that worked on every platform out of the box. The biggest problem here is the slack-android-app in-app-video-player. The webm video at least gives a preview image and works on all other platforms.