IInvidious – an Apple II Invidious and Peertube client

IInvidious (pronounced Two-nvidious) is a simple Invidious (Youtube) and Peertube client for the Apple II. It can:

  • Search videos on an instance
  • Display the search results, along with the thumbnail
  • Play videos with sound
  • Fast-forward and rewind, pause and stop
  • Read subtitles, in the language you prefer

It can connect to both Invidious and Peertube instances.

Screenshots:

Searching for, and playing, “Camera Silens – Réalité”

Requirements:

IInvidious should run on any 65*02 64k Apple II with two serial cards. The IIgs is not yet supported. In addition to that, it requires a surl-server proxy to handle the transcoding and resampling.

Installing the surl-server proxy:

See the dedicated surl-server page, or this instruction video.

Transferring the floppy to your Apple II:

Download the latest iinvidious-65c02.po or iinvidious-6502.po floppy image from the Github Releases page, depending on your Apple II model :

Apple II modelFloppy image
][+, IIe, 6502 CPU with 64kB of RAMiinvidious-6502.po
//c, //c+, IIe enhanced or platinum, 65c02 CPU with 128kB of RAMiinvidious-65c02.po

Transfer it to your Apple II using ADTPro (you may prefer the video format), or with your STP floppy if you have it setup.

Playing videos

  • Input an URL to a Peertube/Invidious instance, like https://invidious.fdn.fr or https://peertube.fr.
  • Input keywords to search for videos matching them.
  • Navigate through the results with the left and right arrow keys, play a video with Enter or enter a new search with Escape.

Two-ports serial setup

To play video using IInvidious, you will need to use two serial cables and USB serial adapters. The second serial cable should be plugged into the printer port (or slot 1), and the corresponding USB adapter is named aux_tty in surl-server’s configuration file. More information about this is available in Wozamp’s user manual and in the surl-server setup page.

You can expect 13 to 23 fps, depending on how dynamic the video is and the settings you use.

The proxy’s CPU power is also, for once, to be taken into account; a Raspberry Pi 3 can’t decode faster than realtime, so preloading can be a bit long, depending on the streamed video’s duration.

Development log

First step: assemble enough things together to that we can fetch a video file URL from an Invidious instance, from a Youtube video ID:

Screen record of my emulator, loading and playing a video by ID

A few words about the “assembling things”. Most of this project, so far, is reusing parts I wrote for previous projects (Mastodon, Wozamp, STP, …). The code I had to write was, almost 100%, the glue between those parts and the UI. Giving a look at the Makefile for IInvidious, here are the different parts:

iinvidious_SOURCES := \
  # The audio-video streamer itself (from Wozamp)
  ../lib/surl/surl_stream_av.s \

  # IInvidious-specific
  main.c \                # The launcher and main UI
  videoplay.c \           # The video player, sets up the streamer
  config.c \              # The config screen UI

  # UI helpers
  ../lib/hgr.c \          # HGR/text mode switching                
  ../lib/clrzone.s \      # Fast clear of parts of screen
  ../lib/scrollwindow.c \ # Scroll-window handling
  ../lib/scroll.s \       # Fast screen scroller
  ../lib/dputc.s \        # Fast character output
  ../lib/dgets.c \        # Good-enough text input routine

  # System helpers
  ../lib/path_helper.c \           # Working-directory helper
  ../lib/extrazp.s \               # Def for a few bytes of zeropage
  ../lib/malloc0.c \               # malloc wrapper with error control
  ../lib/fastirq$(iigs_suffix).s \ # IRQ handler, faster than 
                                   # the ProDOS-based one

  # Serial communication
  ../lib/serial/simple_serial.c \           # The core of it
  ../lib/serial/simple_serial_configure.c \ # Ports configuration
  ../lib/serial/simple_serial_io.s \        # Fast I/O routines
  ../lib/serial/serial_read_no_irq.s \      # Very fast serial reading
                                            # without IRQ

  # Serial hardware handling
  ../lib/serial/$(serial_hw)/common.s \     # The core of it
  ../lib/serial/$(serial_hw)/control.s \    # Settings handler (parity, etc)
  ../lib/serial/$(serial_hw)/no_irq.s \     # IRQ-free I/O

  # Serial proxy code
  ../lib/surl/surl_core.c \                 # The core of it (setup and
                                            # functions used in every 
                                            # project)
  ../lib/surl/surl_ping.c \                 # Comms checker (allowing for
                                            # serial config)
  ../lib/surl/surl_read_with_barrier.s \    # Fast data reader, IRQ-less
  ../lib/surl/surl_get_json.c \             # JSON parsing via proxy
  ../lib/strsplit.c \                       # Used for JSON parsing

Second step: Add a bit of UI – a logo, a search, a way to navigate the search results:

Searching videos and browsing the results, on my Apple //c

Third step: Realize it’s not very difficult to add Peertube support (mostly the API endpoints and JSON selectors differ), so do that:

Searching on Peertube, on the emulator

Fourth step: Error handling, bells and whistles (like video duration), cleanups.

Then subtitles, if I still have enough memory to fit the feature in. This feature will require extending the serial proxy protocol, to allow passing a subtitles URL to the transcoder in the proxy – subtitles support exists for Wozamp, but only handles subtitles embedded in the video container, or from the video URL with the extension replaced by “.srt”. Passing in an arbitrary URL is not yet possible.

So, subtitles roadmap:

  • client-side, add the JSON queries to fetch a subtitles URL from Invidious/Peertube server
  • proxy-side, extend proxy protocol to pass that URL to the streamer and client-side, pass that URL to the proxy
  • Making sure the hundreds of bytes necessary for steps 1 and 2 to fit in memory.

Here is the fetching of the subtitle URL client-side, the passing of the URL to client to proxy. No cleanup was necessary to fit everything.

Fifth step done: we have subtitles!

Playing a video with subtitles, on the emulator