Hi there,
It is said that where there is a screen, there must be a bad apple. Where there is a Dash, there must be one, too!
from dash import Dash, html, dcc, Input, Output, State
import requests
frames = requests.get(
"https://raw.githubusercontent.com/IcToxi/datasets/main/bad_apple_frames.json"
).json()
app = Dash(__name__)
app.layout = html.Div(
[
html.Pre(id="bad-apple-x-show"),
dcc.Store(data=frames, id="bad-apple-x-frame"),
dcc.Interval(id="bad-apple-x-interval", interval=1000 / 15, n_intervals=0),
html.Audio(src="/assets/bad_apple.m4a", autoPlay=True, loop=True),
]
)
app.clientside_callback(
"((n, frames) => n % Object.keys(frames).length && frames[n % Object.keys(frames).length])",
Output("bad-apple-x-show", "children"),
Input("bad-apple-x-interval", "n_intervals"),
State("bad-apple-x-frame", "data"),
)
if __name__ == "__main__":
app.run(debug=True)
I supposed to put an online resource, but cross-origin is too troublesome.
ffmpeg -i bad_apple.mp4 -map 0:a -c copy bad_apple.m4a
The method to extract the frames is as below:
- First, you must have a video file, and then extract its frames and save it as pictures. You can adjust the frame rate and picture quality.
ffmpeg -i bad_apple.mp4 -f image2 -r 15 -qscale:v 2 ./img%05d.jpg
- Convert these pictures to characters.
from PIL import Image
import os
import json
from tqdm import tqdm
ascii_char = list(
"$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
)
WIDTH = 144
HEIGHT = 48
def get_char_from_pixel(r, g, b, alpha=256):
if alpha == 0:
return " "
length = len(ascii_char)
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = (256.0 + 1) / length
return ascii_char[int(gray / unit)]
def ascii_pic_from_pil(path):
text = ""
im = Image.open(path)
im = im.resize((WIDTH, HEIGHT), Image.Resampling.NEAREST)
for h in range(im.size[1]):
for w in range(im.size[0]):
text += get_char_from_pixel(*im.getpixel((w, h)))
text += "\n"
return text
frame = {}
for root, dirs, files in os.walk("./bad_apple"):
for f in tqdm(files):
if f.endswith(".jpg"):
frame |= {
(int(f.replace("img", "").replace(".jpg", ""))): ascii_pic_from_pil(
os.path.join(root, f)
)
}
with open("frames.json", "w") as f:
f.write(json.dumps(frame, indent=2, sort_keys=True))
Hope you like this. XD
Keywords: Bad Apple, dcc.Store
, Cross Origin, FFmpeg, Pillow
Other Daily Tips series:
Daily Tips - If I have a Bunch of Triggers
Daily Tips - Share the Function
Daily Tips - How many Ways to share Dash in a company?
Daily Tips - Give your Component a Name
Daily Tips - Share Dash to Social Media
Daily Tips - Double-click to open Dash
Daily Tips - What rows of data have I modified?
Daily Tips - Write the Simplest Client-side Callback
Daily Tips - Some simple Expressions
Daily Tips - IoT? Real Real-time Data and Live Update
Daily Tips - Which formatter is your favorite?
Daily Tips - Convert a React Component to Dash
Daily Tips - Real-time Logs on Dash