Bad Apple printed out on the console with Python!

Overview

bad-apple

Bad Apple printed out on the console with Python!

Preface

A word of disclaimer, while the final code is somewhat original, this project is an amalgamation of different code snippets that I found online. As the main YouTube Video begins to gain traction, I feel the need to inform the audience that this code is NOT ENTIRELY ORIGINAL.

The concept of playing Bad Apple!! on a Command Line Interface (CLI) is not a novel idea and I am definitely not the first.

There are many iterations and versions around YouTube and I wanted to give it a shot. The intent of posting the video on YouTube was to show a few friends of a simple weekend project that I whipped up in Python.

My own video can be found here.

Running this code

Thanks to TheHusyin for adding a requirements.txt file for easier installs.

First, ensure that you set your terminal to the directory of this repository.

cd bad-apple

Install the necessary dependencies and packages by using:

pip install -r requirements.txt

And to run the code:

python touhou_bad_apple_v2.py

And just follow the on-screen prompts.

Performance optimizations

Currently, my implementation of a rudimentary static time.sleep() function results in an incremental error over time. This thus leads to the frame accucracy drifting.

I am also looking into improving frame extraction and generation times.

Current known issues and bugs

Despite being a somewhat simple program, my crappy implementation has led to a lot of unresovled bugs and issues. I am currently looking at fixing some of them.

  1. block=False is not supported in Linux

I am currently trying to find alternatives to the playsound library. Using two different threads is not an option currently as I was running into desynchronization issues.

This issue has been fixed in v3, alongside other performance improvements.

  1. No such file or directory: 'ExtractedFrames/BadApple_1.jpg'

Not really sure how this is happening, but will be looking into fixing it. I was unable to replicate the error but I assume it is due to my botchy implementation of file directories for the assets.

Version descriptor

  1. touhou_bad_apple_v1.py

First rudimentary version that accomplishes basic frame extraction and animation. Utilizes threads, but suffers from heavy synchronization issues.

  1. touhou_bad_apple_v2.py

Extended version that includes a "GUI", some basic file I/O. Suffers from slight synchronization issues. Core program logic was completed in 24 hours with some minor tweaks and comments afterwards.

  1. touhou_bad_apple_v3.py

Current development version. Improved frame time delay and better file I/O. Looking to implement threading to expedite frame extraction and ASCII conversion.

Functions

The main functions will be listed here.

play_video()

Reads the files from the previously generated ASCII .txt files and prints it out onto the console.

play_audio()

Plays the bad apple audio track.

progress_bar(current, total, barLength=25)

A simple progress bar function that generates the status of both frame extraction and ASCII frame generation. This code was taken from a StackOverflow thread.

current is the current value/progress of the process.

total is the desired/intended end value of the process.

barLength=25 sets the length of the progress bar. (Default is 25 characters)

ASCII Frame generation

Not a particular function, but a group of functions.

resize_image()

greyscale()

pixels_to_ascii()

These functions are called in the ascii_generator() function to convert image files to ASCII format and stores them into .txt files.

Note that the ASCII conversion code is not original, and was taken from here.

Comments
  • [touhou_bad_apple_v4.5.py] pygame.error: Unrecognized audio format

    [touhou_bad_apple_v4.5.py] pygame.error: Unrecognized audio format

    Hey :) Its been a while since my last ticket :) I have a new one for yaa. Even when this project was a weekend project. im still amazed about your progress..

    It seems to be that there is something wrong with the audio format...

    see log:

    python3 touhou_bad_apple_v4.5.py

    Select option:

    1. Play
    2. Exit ============================================================== Your option: 1 Please enter the video file name (file must be in root!): BadApple.mp4 MoviePy - Writing audio in audio.mp3 MoviePy - Done.
      Beginning ASCII generation... Progress: [####################### ] 99% Frame 6570 of 6571 framesASCII generation completed! ASCII generation time: 28.546977519989014Traceback (most recent call last): File "touhou_bad_apple_v4.5.py", line 181, in main() File "touhou_bad_apple_v4.5.py", line 170, in main play_audio('audio.mp3') File "touhou_bad_apple_v4.5.py", line 24, in play_audio pygame.mixer.music.load(path) pygame.error: Unrecognized audio format
    opened by 0n1cOn3 8
  • block=False is not supported in Linux

    block=False is not supported in Linux

    block=False is not supported in Linux, you may need to add an thread to execute playsound():

    import threading ...

    threading.Thread(target=playsound, args=("tng_bad-apple.mp3",)).start()

    opened by 0n1cOn3 5
  • ModuleNotFOundError: No module named 'PIL'

    ModuleNotFOundError: No module named 'PIL'

    I never used Python but I really wanted to try this. I followed all the steps.

    \Desktop\bad-apple-master\touhou_bad_apple_v3.py", line 7, in from PIL import Image ModuleNotFoundError: No module named 'PIL'

    opened by ABongoCat 1
  • Licence/Copyright?

    Licence/Copyright?

    Amazing job! I have some ideas for things I'd like to make by adapting your code, but I can't with no copyright info attached to the code. I would suggest the timeless GNU Public License: https://www.gnu.org/licenses/gpl-3.0.en.html

    opened by helmutcarter 0
  • Bug correction

    Bug correction

    Hope you find this commit helpful :) Simplified play_video function using a foreach loop and consequently corrected a bug that throws an array out of bounds exception Also added a video termination message at the end

    opened by FranzRome 0
  • V4.5 works flawless on fedora but:

    V4.5 works flawless on fedora but:

    At the end, theres that. :I it works perfectly until it reaches the end Python 3.9 has been used. Afaik Python 3.10 has some issues cause this hasn't been optimized for Python 3.10 or newer.

    Traceback (most recent call last):
      File "/home/hax/GitHub/bad-apple/touhou_bad_apple_v4.5.py", line 181, in <module>
        main()
      File "/home/hax/GitHub/bad-apple/touhou_bad_apple_v4.5.py", line 171, in main
        play_video(total_frames=total_frames)
      File "/home/hax/GitHub/bad-apple/touhou_bad_apple_v4.5.py", line 37, in play_video
        sys.stdout.write("\r" + ASCII_LIST[frame_number])
    IndexError: list index out of range 
    
    opened by 0n1cOn3 0
  • Not really an issue, just some tweaks, from a new-ish scripter

    Not really an issue, just some tweaks, from a new-ish scripter

    Forked your repo, and had a look, also had a look about the suggestions made by the other user, but honestly, cv2 and the way you're currently doing the ascii conversion, is over my head slightly. If I properly sat down and read it, I might get somewhere, but anyways. I've tweaked your script to also use threading on the frames, so it should be faster. Also, completely removed the need to save to a file, twice, by just directly passing the cv2 result to PIL, and then outputting the frames, though I do like the idea for keeping the frames, which is why I'm also looking into perhaps RLE compressing the frames into a single file, instead of having a whole folder of 7kb ASCIIs. I'm not really sure if you wanted the tweaks I made in your version, so I made it as a separate file on my repo and put this as a issue, instead of a PR (though if comments were a thing, I'd put it there), if you just want to take a look. Just as someone who vaguely knows Python, this was a nice project to at least be able to work on.

    Oh, and progress bar still works!

    opened by BlakeTech 9
  • Possible optimizations in ASCII generation, video quality, and video playback

    Possible optimizations in ASCII generation, video quality, and video playback

    Hi, I saw the code on touhou_bad_apple_v2.py and I though of some possible speed improvements right off the bat.

    First is ASCII generation. As you're doing right now, the best way to improve processing speed is by creating a Pool and allocating each frame to a worker until the frame extraction is over. The disadvantage is that you lose the current progress bar you have implemented, and instead will need something more complex like an N lines progress bar, one for each worker in the pool, or a signaling method between threads, like a semaphore, and is just too much work for what the current project is aiming for. You can also improve the video quality by adding more characters to the list, more specifically a space(all black) " " and a block character(all white) "\u2588", and adapting the padding calculation on line 86 to include the new characters.

    Another improvement, and probably the most important one, is saving the ASCII frames to a single file containing all frames, instead of multiple files. The reasoning is that opening and closing files takes time, which would be better spent synchronizing the frames in the terminal.

    Checking files also takes time. As of right now, you are manually checking every single .txt file for all the frames and checking if they exist. This can be done much faster if you use instead os.listdir() and filter the results containing the string .txt, then count the results(or a single file if you use the approach above). Also, please always use os.path.join() instead of manually using /. Reasoning is that the os.path library provides cross-platform separators and better handling of absolute paths, which is much less error prone.

    I could make a fork and do those changes, but I think it would be very useful if you did them yourself, since you can learn new skills and functions with them. Tell me what you think about my suggestions, then close this issue later.

    Edit: my mistake, I just noticed you changed to a white background in the video. Correct characters are a space(all white) " " and a block character(all black) "\u2588"

    opened by karoush1 1
Owner
CalvinLoke
CalvinLoke
Script to automate the scanning of "old printed photos"

photoscanner Script to automate the scanning of "old printed photos" Just run: ./scan_photos.py The script is prepared to be run by fades. Otherw

Facundo Batista 2 Jan 21, 2022
Python script to commit to your github for a perfect commit streak. This is purely for education purposes, please don't use this script to do bad stuff.

Daily-Git-Commit Commit to repo every day for the perfect commit streak Requirments pip install -r requirements.txt Setup Download this repository. Cr

JareBear 34 Dec 14, 2022
General tricks that may help you find bad, or noisy, labels in your dataset

doubtlab A lab for bad labels. Warning still in progress. This repository contains general tricks that may help you find bad, or noisy, labels in your

vincent d warmerdam 449 Dec 26, 2022
Really bad lisp implementation. Fun with pattern matching.

Lisp-py This is a horrible, ugly interpreter for a trivial lisp. Don't use it. It was written as an excuse to mess around with the new pattern matchin

Erik Derohanian 1 Nov 23, 2021
Kellogg bad | Union good | Support strike funds

KelloggBot Credit to SeanDaBlack for the basis of the script. req.py is selenium python bot. sc.js is a the base of the ios shortcut [COMING SOON] Set

null 407 Nov 17, 2022
About A python based Apple Quicktime protocol,you can record audio and video from real iOS devices

介绍 本应用程序使用 python 实现,可以通过 USB 连接 iOS 设备进行屏幕共享 高帧率(30〜60fps) 高画质 低延迟(<200ms) 非侵入性 支持多设备并行 Mac OSX 安装 python >=3.7 brew install libusb pkg-config 如需使用 g

YueC 124 Nov 30, 2022
🍏 Make Thinc faster on macOS by calling into Apple's native Accelerate library

?? Make Thinc faster on macOS by calling into Apple's native Accelerate library

Explosion 81 Nov 26, 2022
Process RunGap output file of a workout and load data into Apple Numbers Spreadsheet and my website with API calls

BSD 3-Clause License Copyright (c) 2020, Mike Bromberek All rights reserved. ProcessWorkout Exercise data is exported in JSON format to iCloud using

Mike Bromberek 1 Jan 3, 2022
Automatically skip sponsor segments in YouTube videos playing on Apple TV.

iSponsorBlockTV Skip sponsor segments in YouTube videos playing on an Apple TV. This project is written in asycronous python and should be pretty quic

David 64 Dec 17, 2022
Singularity Containers on Apple M1 (ARM64)

Singularity Containers on Apple M1 (ARM64) This is a repository containing a ready-to-use environment for singularity in arm64 (M1). It has been prepa

Manuel Parra 4 Nov 14, 2022
SkyPort console user terminal written in python

SkyPort terminal implemented as a console script written in Python Description Sky Port is an universal bus between user software and compute resource

Sky Workflows 1 Oct 23, 2022
Battle-Ship - Python-console battle ship

Battle-Ship this SHOULD work in lenux(if i spelled it wrong spam issues till I fix it) the thing that maby wont work is where it clears the screen the

pl608 2 Jan 6, 2022
Org agenda in the console

This Python script reads an org agenda file (i.e. a regular org file with some active dates) and displays an interactive and colored year calendar with detailed information for each day when the mouse hovers a specific date. Else, it shows event for a the current week.

Nicolas P. Rougier 113 Jan 3, 2023
Cross-platform config and manager for click console utilities.

climan Help the project financially: Donate: https://smartlegion.github.io/donate/ Yandex Money: https://yoomoney.ru/to/4100115206129186 PayPal: https

null 3 Aug 31, 2021
skimpy is a light weight tool that provides summary statistics about variables in data frames within the console.

skimpy Welcome Welcome to skimpy! skimpy is a light weight tool that provides summary statistics about variables in data frames within the console. Th

null 267 Dec 29, 2022
Werkzeug has a debug console that requires a pin. It's possible to bypass this with an LFI vulnerability or use it as a local privilege escalation vector.

Werkzeug Debug Console Pin Bypass Werkzeug has a debug console that requires a pin by default. It's possible to bypass this with an LFI vulnerability

Wyatt Dahlenburg 23 Dec 17, 2022
Basic-Killfeed - A simple DayZ Console Killfeed

Basic-Killfeed A simple DayZ Console Killfeed. Setup Install Python Version 3.10

Nick 1 Apr 25, 2022
In this project we will implement AirBnB clone using console

AirBnB Clone In this project we will implement AirBnB clone using console. Usage The shell should work like this

Nandweza Allan 1 Feb 7, 2022
A python script made for personal use to monitor for sports card restocks on target.com since they are sold out often

TargetProductMonitor A python script made for personal use to monitor for sports card resocks on target.com since they are sold out often. When a rest

Bryan Lorden 2 Jul 31, 2022