WWWALKMAN

WWWALKMAN

Made by
Eric Rabinowitz
Thanks to

WWWALKMAN is a speculative design work reimagining how we share content on the Internet, bypassing the use of URLs, which can be tracked, paywalled, and modified at any time. WWWALKMAN utilizes cassette tapes and the sounds of dial-up modems to allow participants to record webpages to tape and remix them. These tapes can then be played back in real time through a live web server.

The project invites participants to consider a time when we could have direct ownership over our media and how we chose to consume and share it, such as by creating mix tapes for friends. The Internet and web were not originally designed for the data tracking, invasions of privacy, and walled gardens we see today—so alternative networks are still possible.

Before improved digital data storage, tapes were commonly used to load programs onto early home computers like the Commodore 64. However, unlike these data tapes, which had to be played beginning-to-end, WWWALKMAN is interruptible because of how freeform HTML can be. HTML can be sent to the browser incomplete or mashed together, and the browser will still do its best to render it instead of throwing errors.

The project uses a Rasberry Pi computer and a cassette player/recorder, with audio cables connected to both the computer’s audio input and output.

Recording websites

To record a website to tape, first its HTML data is downloaded (also known as “web scraping”). All scripting and metadata/SEO tags are removed, and all images are downloaded and converted to a low-resolution base64-encoded data URL. This is done both to reduce the amount of invisible data played on the tape, as well as to ensure the page-on-tape can run fully offline without making any requests to its original server, which can be tracked. Additionally all external CSS stylesheets are inlined using the juice package, so that tapes can be played at any point, and its content will be mostly styled correctly without having to play the tape from the beginning to decode full stylesheets.

The resulting HTML is then converted to audio using a program called minimodem, which modulates binary data into discrete frequencies using the frequency-shift keying (FSK) modulation scheme. This technique was used by early dial-up internet modems to transmit data as audible tones over telephone lines—reusing a medium designed for human voice. This is also how Caller ID information is transmitted to your phone.

Bits represented as sound waves. Image from Wikipedia
Bits represented as sound waves. Image from Wikipedia

This audio is output from the computer’s headphone jack and recorded onto a cassette tape. During the exhibition, visitors could type any URL into a console and record its content to an empty tape.

Some of the webpages recorded to tape and streamed by participants

Playback

WWWALKMAN uses a Raspberry Pi, which runs a simple Bun JavaScript web server on the local network. Anyone can connect to this webpage to interact with the content of the cassette players. No HTML files are stored on the server—instead, the Raspberry Pi continually decodes the audio being played in from the cassette player using the minimodem program.

Tape player audio is split between the Raspberry Pi and headphones, so visitors can listen in to the raw data stream while the webpage is rendered
Tape player audio is split between the Raspberry Pi and headphones, so visitors can listen in to the raw data stream while the webpage is rendered

When someone connects to the web server, an HTTP response is sent that never closes. Instead, it continually streams chunks of data as it is decoded from the tape. To the browser and end-user, this appears like a webpage that is still loading over a very slow connection.

Here is a snippet of the server code which starts the minimodem process and an HTTP server that continually streams chunks of the decoded audio:

typescriptconst proc = Bun.spawn(['minimodem', '-r', baudRate], {
  stderr: 'pipe',
});
proc.stdout.pipeTo(stream);

let buf = '';
const stream = new WritableStream({
  write(chunk) {
    const str = new TextDecoder().decode(chunk);
    buf += str;
    if (buf.length >= 32) {
      state.ready.resolve(buf);
      buf = '';
      state.ready = new AsyncSubject();
    }
  },
});

Bun.serve({
  async fetch(req: Request) {
    const asyncIterator = (async function* () {
      while (true) {
        const data = await state.ready.promise;
        if (data) yield data;
      }
    })();

    return new Response(new ReadableStream({
      async pull(controller) {
        const { value, done } = await asyncIterator.next();
        if (done) {
          controller.close();
        } else {
          controller.enqueue(value);
        }
      },
    }));
  },
  port,
});

At any times, tapes can be paused, rewound, fast-forwarded, or ejected and replaced with another tape. The server will continue to serve the content of anything currently playing, allowing users to live mix and create unique web pages like a DJ. Additionally, due to the nature of CSS (cascading style sheets), any CSS styles played later will take precedence over earlier ones, allowing for styles from one site to be applied to another. Introducing a time-delay to the cascade of styles also enables the creation of tape-based animations.

No CSS animations are used. Changes are a result of CSS styles being streamed from the tape over time.

Radical Networks

This project was created during Radical Networks, a class taught at NYU IMA Low Res by Sarah Grant, who started a conference of the same name. The course challenges students to think critically about how communication and networking technologies work, who controls them, and who benefits. I was inspired to explore the physicality of networks by making the data audible—the same types of processes are used for WiFi and ethernet, but their speed and seamlessness make the data transfer seem almost magical, though their physical impact is real.

© 2023 Eric Rabinowitz