Skip to content

Instantly share code, notes, and snippets.

@aishenreemo
Last active October 14, 2025 22:50
Show Gist options
  • Select an option

  • Save aishenreemo/1902ce9d938202fe03ae9377ac69a7e9 to your computer and use it in GitHub Desktop.

Select an option

Save aishenreemo/1902ce9d938202fe03ae9377ac69a7e9 to your computer and use it in GitHub Desktop.
ascii-bad-apple

ASCII Art Bad Apple

Here is a step-by-step procedure on how to play Bad Apple on your Linux terminal (could also work with any video you want if you use your common sense).

  1. Install these tools.
  • ffmpeg: Processes the Video into series of images/frames.
  • jp2a: Image to ASCII Art converter.
  • python: ASCII Art video player.
  • python-pygame: Just to play sound asynchronously.
  • yt-dlp: Download videos from Youtube.
  1. Create a directory called bad_apple and change directory inside that directory.
mkdir bad_apple
cd bad_apple
  1. Download the video as mp4 via yt-dlp, then convert it to mp3 via ffmpeg.
yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" https://www.youtube.com/watch\?v\=FtutLA63Cp8\&ab_channel\=kasidid2 -o bad_apple.mp4
ffmpeg -i bad_apple.mp4 bad_apple.mp3

Now if you performed a ls, both the video file mp4 and audio file mp3 should appear.

  1. Create a folder named frames and frames_ascii.
  • frames/: here you will store the series of images frame by frame.
  • frames_ascii/: here you will store the series of ASCII arts frame by frame.
mkdir frames
mkdir frames_ascii
  1. Convert the video into series of images/frames via ffmpeg.
ffmpeg -i bad_apple.mp4 -vf fps=30 frames/out%05d.jpg
  1. Convert the frames into ascii art via jp2a.
cd frames
for file in *; do jp2a --colors --width=137 --height=37 $file > "../frames_ascii/${file%.jpg}.txt"; done
cd ..

The 137 and 37 corresponds to the width and height of the ASCII art so change it if you want.

  1. Now create a python file and paste this code inside.
from pygame import mixer
import time
import sys
import os


if __name__ == "__main__":
    audio_file = "bad_apple.mp3"
    frames = sorted(os.listdir("frames_ascii"))
    frames_len = len(frames)

    mixer.init()
    mixer.music.load(audio_file)
    mixer.music.play()

    audio_length = mixer.Sound(audio_file).get_length()

    sys.stdout.write("\033[?25l")
    os.system("clear")

    while mixer.music.get_busy():
        pos = mixer.music.get_pos() / 1000.0
        percentage = pos / audio_length
        file_pos = int(percentage * frames_len)
        file_path = os.path.join(
            "frames_ascii",
            "out{:05}.txt".format(file_pos)
        )

        file_str = "\033[35m{}\033[0m".format(file_path)
        percentage_str = "\033[33m{:.2f}%\033[0m".format(percentage * 100)
        pos_str = "\033[31m{:.2f}\033[0m / \033[32m{:.2f}\033[0m"\
            .format(pos, audio_length)

        with open(file_path, "r") as file:
            caption = f"{pos_str} : {percentage_str} : {file_str}    "
            sys.stdout.write("\033[0;0H")
            sys.stdout.write(file.read())
            sys.stdout.write(caption)

        time.sleep(1 / 30)

    sys.stdout.write("\033[?25h")
  1. Run that script and done!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment