Tuesday, December 29, 2015

Python how to check if a particular key is in a dictionary

So, making a program based on code from a much more competent programmer, they had gotten as far as capturing our data in a structure called a 'dictionary' which is one of the things that makes python very useful.

My first mistake was in thinking that dictionaries and lists are interechangable. They aren't; lists are single-column and numerically indexed like arrays, dictionaries are a column of tuples, essentially two columns. Lists are declared as list = [], dictionaries are declared as dict = {}. The delight of dictionaries is that they don't have to be iterated through like lists to find a value. You can just ask it for the value at a particular key (first column) and BAM you get back the value (second column). Also, it turns out to be very easy to find if a particular key exists in the entire dictionary. You just say if key in dict: A couple of links showing this:

http://stackoverflow.com/questions/1602934/check-if-a-given-key-already-exists-in-a-dictionary
http://stackoverflow.com/questions/19241680/python-check-that-key-is-defined-in-dictionary


Tkinter binding Return key to an Entry widget

For my GUI for my project, I wanted to pop up a text entry widget to get a parameter for the user, and have it disappear and return whatever was entered when they pressed the "Return" key. Several examples of using the Entry widget had an "Enter" button, but that would be too much extra mouse motion for my customers (it makes sense for a form with several parameters). I'm also still not to the point of programming an entire GUI, I'm just trying to pop up some windows whenever my program needs input, so in that regard I'm already not doing this right. However, I copied the example methodology that I used to make the button window earlier, which was to define a class for the general type of dialog I wanted, and then a method that instantiated an object of that class, ran it, destroyed it, and returned the result. On my windows version of python, things were a little bit different than in some examples that I found, and the big trick was getting the "Return" key binding to work right.

Here are the top two links that I found for using Entry widgets. They don't directly show using a class (both have the call to mainloop() right in line with the rest of the code).

This link is slightly lighter in example code than the next, but it shows use of get(), focus_set(), delete(), and insert(). Like the next link, its example uses a button to call get(). This link has the example of how to set the width using entry.config(width=width).

http://effbot.org/tkinterbook/entry.htm


This one shows how to insert default text into entry widgets and how to use the get() method. It also shows the delete() method for clearing an entry widget before inserting default text, but the examples use some kind of 'END' keyword that didn't work for me, and for me the widgets started empty anyhow. It then has some examples of nice formatting, but I actually just wanted to have the text entry frame and have the user prompt about what to enter in the title bar:

http://www.python-course.eu/tkinter_entry_widgets.php


Both of the above links seemed to show the Entry widget being imported from Tkinter, but in my case, it turned out that for me for some reason I couldn't find Entry in the Tkinter library, instead it was in the ttk libary. I seem to have lost the link that gave me the clue to try that.

Here's the example of how to use the root window .title property to make the text I wanted appear in the title bar of the entry window:

https://bytes.com/topic/python/answers/34607-how-change-text-title-bar-tkinter-windows



The next few links had clues about binding the Return key to a callback. However none of them were using the Entry widget in a class like I was, so the way that they had the callback contain references to the entry object didn't work for me.

Here's a really basic example showing binding, but doesn't show using the get() function:

http://stackoverflow.com/questions/16996432/cant-figure-out-how-to-bind-the-enter-key-to-a-function-in-tkinter


This one showed a callback, but I didn't notice until much later that it's doing something interesting by passing a "textvariable" parameter into the definition of the Entry widget that the callback is then accessing. This is the use of a "StringVar" type that one of the previous links disparaged and which I was trying to do without.

http://www.java2s.com/Code/Python/GUI-Tk/BindenterkeytoEntry.htm



The following super basic example turned out to have the solution, in that it showed the callback bound to the Return key using the event argument to the callback to find a pointer the entry window so that it's get() function could be called:

https://mail.python.org/pipermail/tkinter-discuss/2008-June/001447.html


So, here is the first version of the code that seemed to work for me:

class NoButtonEntry(object):
def __init__(self, title, default):
root = self.root = Tkinter.Tk()
root.title(title)

e = ttk.Entry(root)
e.config(width=(len(title)+20))
if (default):
e.insert(0,default)
e.bind('',self.return_it)
e.pack()
e.focus_set()

root.protocol("WM_DELETE_WINDOW", self.close_thing)
root.deiconify()
root.lift()
root.call('wm', 'attributes', '.', '-topmost', True)
root.call('wm', 'attributes', '.', '-topmost', False)
def return_it(self, event=None):
self.returning = event.widget.get()
self.root.quit()
def close_thing(self):
self.returning = None
self.root.quit()
def mentry(title,default=None):
newentry = NoButtonEntry(title,default)
newentry.root.mainloop()
newentry.root.destroy()
return newentry.returning
serial = mentry(title='Enter text or return to accept default',default='0')

Update: So, later I went on to try to add an "accept" button to my pop-up and found myself not able to make that work either. The solution turned out to be so simple, after looking at example after example. If I defined the entry object as an object within my class, by saying something like self.e = ttk.Entry(root) instead of e = ttk.Entry(root), then the callback for my button could find the entry object! Doing it the other way made the declaration of the entry object local only and not accessible to other objects in the class In the end, I learned to just always make objects in my GUI class members of that class so that they could all access each other.

Here is just a great general tutorial on how use Tkinter including how to define entry and button objects, with solid examples:

http://python-textbok.readthedocs.org/en/latest/Introduction_to_GUI_Programming.html


Here is the example that probably helped me figure it out, because the OP shows doing it the way I was trying to do it, and somebody answers with an example of doing it correctly:

http://stackoverflow.com/questions/9355742/python-tkinter-button-entry-combination


Oh, and here's more info on how to set the focus to the entry widget. Not sure why I didn't use this except that the answer seems to be for a Tkinter Entry widget and I'm using a ttk Entry widget:

http://stackoverflow.com/questions/13626406/setting-focus-to-specific-tkinter-entry-widget


So now my code looks like this:

class NoButtonEntry(object):
def __init__(self, title, default):
root = self.root = Tkinter.Tk()
root.title(title)

self.e = ttk.Entry(root)
self.e.config(width=(len(title)+20))
if (default):
self.e.insert(0,default)
self.e.bind('',self.return_it)
self.e.pack(side="left")
self.e.focus_set()

self.b = Tkinter.Button(root,text="Accept",command=self.return_it)
self.b.pack(side="left")

root.protocol("WM_DELETE_WINDOW", self.close_thing)
root.deiconify()
root.lift()
root.call('wm', 'attributes', '.', '-topmost', True)
root.call('wm', 'attributes', '.', '-topmost', False)
def return_it(self, event=None):
# Note I no longer have to care about whether it was from an event
self.returning = self.e.get()
self.root.quit()
def close_thing(self):
self.returning = None
self.root.quit()
def mentry(title,default=None):
newentry = NoButtonEntry(title,default)
newentry.root.mainloop()
newentry.root.destroy()
return newentry.returning
serial = mentry(title='Enter text or return to accept default',default='0')

Tuesday, December 15, 2015

Serial Port I/O in Python

From digging through Tom's code and googling stuff, it seems rather straightforward.

Need to include:
import serial

To get a module called not Serial but PySerial.

This doesn't come with most python installations, but it's quick to download installers, as demonstrated in this adafruit tutorial:
https://learn.adafruit.com/arduino-lesson-17-email-sending-movement-detector/installing-python-and-pyserial

Which gets the installer from here:
https://pypi.python.org/pypi/pyserial

Here are a couple of really nice forum threads containing example code:
http://stackoverflow.com/questions/676172/full-examples-of-using-pyserial-package
http://stackoverflow.com/questions/1093598/pyserial-how-to-read-the-last-line-sent-from-a-serial-device

Wednesday, November 18, 2015

A python app with Tcl/Tk gui file selection on a BeagleBone with LCD7 touch screen

Trying to pull together a demo user interface for my GSE box, making use of the python code from the previous demo and the hardware that I have on hand which is a BeagleBone with the LCD7 touchscreen. Along the way, a whole lot of involuntary education is occurring, so I'm documenting the journey here.

The plan:
1. Get the BeagleBone powered and figure out how to get the touchscreen working
2. Figure out if the OS for the BeagleBone has python.
3. Study the python code from the demo and glue in tcl/tk file selection dialogs where appropriate to make it more user friendly.
4. Migrate everything over to the Raspberry Pi. Supposedly all the python will be nicely portable.

Notes for each step:

1. Get the BeagleBone powered and figure out how to get the touchscreen working:

Fortunately for me, this was all already working. The hardest part was making sure that I had the polarity of my power chord correct (center positive) and that I was using a supply capable of powering the screen (needed to be 2A). In the end, I am temporarily fudging it with my cut USB chord with power plug wired on that I made for testing the GSE circuit board. The first USB power block that I tried was only 1.2A and this was insufficient, but most dual power blocks supply 2A and one of those runs it just fine. The Beagle Board website actually has very helpful links to recommended power supplies from DigiKey (http://beagleboard.org/peripheral). The Beagle Board powered up fine over USB and I'm able to use my trusty PuTTY to log into it using the default password over the USB cable. With the 2A power to the LCD7, the board finds the screen automatically, and loads a desktop GUI without any fiddling required. It turns out that the microSD card that came with the BeagleBone has a Linux distribution called "Angstrom" that is fully integrated with a Gnome desktop. The only disappointment is that the touchscreen is barely able to control this GUI without a keyboard and mouse. It is possible to drag the mouse pointer around with a finger to the screen, click by pressing, but the resolution of the GUI is so high that it's difficult to position the mouse pointer precisely enough by touch, and there doesn't seem to be an on-screen keyboard (I got an on-screen keyboard in a later Angstrom distribution that I tried, but it's not like an iPhone where it pops up when needed and is optimized for mobile use).

2. Figure out if the OS for the BeagleBone has python.

Once I got a USB keyboard and mouse connected, starting a terminal window and typing "which python" answered the question of whether python was installed. Directly starting python by just typing "python" got me the python prompt. But then, shockingly, "import Tkinter" failed. I could import other standard libraries and execute other python commands, but no Tkinter, tkinter, or _tkinter. Googling has revealed that everybody else has this problem as well. A variety of solutions have been tried, apparently. These include: a) Doing package updates in Angstrom to get Tkinter, but it seems that a simple package update is not sufficient and "rebuilding python" is required! That sounded like way too much, but somebody on a forum thread suggested b) trying out Ubuntu instead. Sadly, I've learned that the BeagleBone distribution of Ubuntu does not come with a desktop interface installed by default like in Angstrom, and its python distribution doesn't come with Tkinter either. However, in the process I learned how to get disk images for both Angstrom and Ubuntu and load them to a microSD card from the safety of my Windows laptop. Notes follow:

b. Get Ubuntu:

I started by first trying to download a new distribution of Angstrom and booting the BB from it, and it worked great. The following link contained perfect handholding for how to get the image file, where to get 7Zip for unpacking it, and where to get a Windows app for writing it to an SD card:

http://beagleboard.org/getting-started#update

Interestingly, the SD card writer app is apparently distributed by Ubuntu. Here is Ubuntu's own page about the App (and other methods of writing SD card images that don't apply to my attempts to do it from Windows):

https://help.ubuntu.com/community/Installation/FromImgFiles

The new Angstrom distribution booted up to the desktop like the original Angstrom distribution that came with the Beagle Board, but still didn't have Tkinter installed.

I was able to repeat the same image installation steps from the above guide while using the Ubuntu image pointed to from here:

http://elinux.org/BeagleBoardUbuntu#BeagleBone_White.2FBlack.2FGreen

Trying it out, I got the familiar screenfuls of grubloader lines on the LCD7, which means that it found the screen. However, no GUI! I logged in using the default password for the distribution, did a "which python" and "python" and to my surprise, still no Tkinter! While I had learned how to get Ubuntu, it hadn't solved my problem, and it turns out that I have to install a gui manually. As far as I can tell, this also means doing the step which I've so far tried to avoid which is putting the BeagleBone on a network. This is something that can't do at work, ironically enough, because of our locked-down IP assignments, and I don't have a Wi-Fi cape for the Beagle Bone, which means the only place I have to plug it into is my router at home.

Here's probably the best link which explains which packages to download and install to get Tkinter in Ubuntu and mentions the command to do the rebuild (the first comment mentions it, but scroll down to the nicer example in the second comment). This thread in particular applies to my case because I noticed that my distribution of Ubuntu had python 2.7 like the OP of this thread:

http://stackoverflow.com/questions/11752174/how-to-get-tkinter-working-with-ubuntus-default-python-2-7-install

This is the link that describes needing to install tk-dev!

The above link points to this sort of unrelated thread which has a very nice reply from someone about the general process for building Python in Ubuntu:

http://stackoverflow.com/questions/6171210/building-python-and-more-on-missing-modules

So, I read a bunch of threads about how to get a GUI for Ubuntu. Most of them agree that for BeagleBone the best one to try is LXDE. Sadly, a lot of people out there trying to make this work are using a Beagle Bone Black which is not what I have and also has on-board flash memory for the OS which I don't have.

Here is a long forum thread with a lot of clues about downloading the LXDE package and getting it to install. The scripts described from the "tools" directory seem to be on the Beagle Bone Black and not on the Ubuntu distro that I have. There's also some warnings about problems with Gnome utilities, which wouldn't affect me trying to install LXDE but I have Gnome in the Angstrom distribution and you never know when a customer is going to try to open something:

https://groups.google.com/forum/#!msg/beagleboard/TtcD9vfOzT8/1stwCBZqNRAJ

This link is mostly about BBB but is hopefully still instructional for my case:

http://elinux.org/Beagleboard:Installing_LXDE

A third option, c, is to try the BeagleBone distribution of Debian from the following link. There might be more of a chance that it will come up with a GUI desktop; BeagleBone's Angstrom distribution which had a GUI comes from the same page, and the Ubuntu distribution actually didn't come from any of BeagleBone's pages. Although reading the comments it seems that the latest Debian image from the BeagleBone page is corrupted so going down this path my end up sucking.

http://beagleboard.org/latest-images

However, when I tried it, the Debian image downloaded and booted fine and went to a GUI. It's a lot faster than Angstrom and looks nicer but doesn't have a lot of applications. It seems to be LXDE. It still doesn't have Tkinter, producing the exact same error message when I try to import it. Supposedly Debian is derived from Ubuntu or vice versa. So I launched into some more online searches:

Keying off of the specifics of the message:

Some search results from the message: File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 42:
This thread which describes the exact message, plus the "Package python-tk has no installation candidate" message I get when trying to do the installation: http://ubuntuforums.org/showthread.php?t=1959073
A thread in which somebody solved the problem by installing the library using "Synaptic", and there's also some rage about why they wouldn't just include the library. Note that I don't seem to have Synaptic on my two working Beagle Bone distros: http://askubuntu.com/questions/513981/tkinter-on-ubuntu-14-04-seems-not-to-work
A page about How to install Tkinter, however it doesn't seem to mention needing tk-dev as another search seems to have turned up: http://tkinter.unpythonic.net/wiki/How_to_install_Tkinter

Some search results from: E: Package 'python-tk' has no installation candidate:
A thread that describes what I'm seeing exactly, but no apparent solutions. A link to a python man page about Tkinter, some suggestions to check the repository list (which is probably my issue since I'm not even on a network)http://ubuntuforums.org/showthread.php?t=361342
The python wiki page mentioned above, which includes such interesting categories as "Tkinter Folklore"https://wiki.python.org/moin/TkInter
An interesting thread with a newbie in which it is eventually resolved that he's not getting to the mirrorshttp://ubuntuforums.org/showthread.php?t=1629083

Searching for Sneakernet options for doing package updates:
A thread full of different ideas, like using Synaptic, an offline repository program, apt-mirror, using apt-get with some kind of verbose arguments, and other hints: http://askubuntu.com/questions/974/how-can-i-install-software-or-packages-without-internet-offline
A short thread where somebody gives a link to Ubuntu's packages web page: http://ubuntuforums.org/showthread.php?t=1488395
A hint which seems to be to run apt-get while navigated to the thumb drive, an interesting idea. Also mentions running dpkg: http://www.linuxquestions.org/questions/linux-newbie-8/install-new-packages-from-usb-drive-using-apt-get-4175417568/
Another instructional about using dpkg: http://www.pendrivelinux.com/how-to-install-deb-packages/

So, in the end, I brought the board home and plugged it into my FiOS router with the Debian OS installed; it got a DHCP address immediately and got on the network with no issues. I began following the instructions for doing package updates for Ubuntu using apt-get, and they worked very smoothly. I had to do the following:

sudo apt-get update
sudo apt-get install python-tk

And that seemed to fix it! From within the python prompt, I was able to import Tkinter and launch dialog boxes like I plan to do with my final program. Apparently, rebuilding python as described in the Ubuntu links was not required.

After getting that to work, I was curious to see if I could get it to work for Angstrom. Angstrom doesn't seem to use apt-get, it uses opkg. I did

opkg update
opkg list | grep tkinter
opkg install tkinter

(I have to check that the last line is exactly the one that I did). Anyhow, it didn't work. I also tried:

opkg install tk-dev

It downloaded and installed, but still no love from "import Tkinter". I was unable to "rebuild" python according to the instructions in the one link that explained it because Make failed with some error message that didn't make any sense, and I couldn't find a "configure" script in the python lib directory. It is probably likely that I haven't actually downloaded the python source directory.

Rather than address that problem directly, I decided to turn back to getting a GUI for the Ubuntu distribution, now that I'd overcome my fear of putting the Beagle Bone on my home network and had gotten through a cycle or two of downloading and installing packages. One of the many web searches I'd done had shown some much nicer-looking Tcl/Tk dialog boxes for a Ubuntu desktop which makes sense since Tkinter uses whatever API is native to the OS. After some searching through links like the following:

http://www.makeuseof.com/tag/10-top-linux-desktop-environments-available/
http://www.javacodegeeks.com/2014/02/5-most-awesome-desktop-environments-for-ubuntu.html

I decided that the desktop I saw must have been the "Unity" desktop which is the one that is most often used with Ubuntu anyhow. It looks like this:

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgokrjrPlbVvsolhVc4Gvl5Fx9-RealsRXfJbUyT-QS-s0v8WZEKjLhHAE_8H8fGGD8UgBqAmvyIiHdfTqQwt64RQRKcwEKLW_tHwI0cEk83i_IMjwegtL7qMzDX7hDgiSMC9wPChIeHEvB/s1600/ubuntu-precise-apps-screenshot.png

So to get Unity, there seems to be a circle of links describing how to install it on an SD card for Beagle Bone. Some of these are for BBB which I don't have, and some talk about "expanding" the disk partition on the SD which again sounds like a lot of work. I guess I should try these though:

http://elinux.org/Beagleboard:Ubuntu_On_BeagleBone_Black#Ubuntu_Precise_On_Micro_SD
http://elinux.org/Beagleboard:Desktops_On_Ubuntu/Debian#Ubuntu_Precise_On_A_microSD_With_Ubuntu_Desktop

I'm not sure yet what the difference is between Unity and Precise. Unity is supposedly the default desktop, while the links mention Precise, and they both look the same in Google image searches.

Here's an instructible about installing Ubuntu with LXDE, presumably the procedure for installing Unity would be similar. Since I apparently already have LXDE with my Debian install, my interest is in trying to experiment with something visually different:

http://www.instructables.com/id/BeagleBone-Ubuntu-OS-LXDE-GUI/









Tuesday, November 10, 2015

How to get a list of com ports in Windows 7 without being administrator

Thanks to my job treating employees like preschoolers, I no longer have the ability to view the device manager on my laptop. I am trying to use the laptop to control a remote device through USB, how to I tell what COM port my USB device has been assigned to? There might be better ways, but what I found is using the heretofore unknown "MODE" command in a DOS window. This will list all printer and com ports with lots of info.

Sources:

This had the key info, although some users on this thread also mention powershell which was the commonly supplied answer on other threads also:
http://superuser.com/questions/835848/how-to-view-serial-com-ports-but-not-through-device-manager

This thread beats on the problem a lot with powershell and some visual basic scripts, but does not reference the MODE command which seems like such an easy solution:
http://empegbbs.com/ubbthreads.php/topics/352184/Windows_command_to_quickly_lis

Multiple lines on Excel scatter plot

For some reason, I just can't make Excel Scatter Plot do multi-line plots the way I thought that it used to. I could swear that you used to be able to select a block of columns, hit plot, your first column would be your x axis, your top row would be your axis and series labels. Nope. Apparently, I'm not the only person who had this idea; a google search for this problem comes back with plenty of rage. Finally, I found a hint that let me devise the following workaround:

Step 1: Select the first two columns of your block and generate a scatter plot. 1st column comes up as the X axis, 2nd column is the Y axis and the labels are correct.

Step 2: Select the third column and do a CTRL-C copy. Go to the graph and CTRL-V paste. Now the second series is plotted as it should be against the first column.

Repeat.

Sources:

The bottom of this thread gave me the clue that you can cut and past directly into a plot:
http://superuser.com/questions/770150/plot-multiple-sets-of-x-y-data-on-a-single-chart

Here's some entertaining rage, although it seems that the main problem was that the OP was confusing line charts with scatter plots:
http://answers.microsoft.com/en-us/office/forum/office_2010-excel/excel-chart-has-no-means-to-setchange-x-axis-data/fe76a57e-cc29-4cf1-bdf3-14857d9e682e?auth=1

Some more rage and a hint on doing manual edits to charts:
http://www.mrexcel.com/forum/excel-questions/512558-create-line-chart-first-column-x-axis.html

Saturday, August 15, 2015

Ghost - Mystery Skulls links

The universe of the Ghost fandom:

Before:

TurnTable Turnabout by MysteryBen27

The beginning:
The Ghost animated video by MysteryBen27

The Fandom:
One of the very first fan animations
Absolutely Glorious MMD with Vivi, Arthur, and Lewis
Which leads to all the remixes:
The Viceroy Remix, which is the one from the MMD
(I must learn more about Viceroy)
Here's the Viceroy remix animated with the original Ghost Video (with some synching issues)
Something by Viceroy
Here's something by Viceroy remixed by Oliver Nelson
Fred Falke Remix (a Cure style remix)
Solidisco Remix
Thomas Newson Remix (basically hard club)
The absolutely incredible Lewis cosplay
(Here's her other cosplay, from Homestuck)
A different MMD featuring just Lewis
The reanimation of the "Oh God It's Lewis" animated comic dub
The "Oh God It's Lewis" animated comic dub by DryeGuy
Many, many animated comic dubs by DryeGuy
The berserk long continuation comic on DeviantArt
So many animated comic dubs by Penelope-Sophia Smith
A video dub of a comic with Lewis, Jack Skellington, and other famous skeletons.
A 7 second animated scene with Vivi and Lewis as furries
Which leads to:
Just Some Motion
and
A different nice video of All Night Long
Parov Stelar's Wikipedia page
Here's Just Some Motion's commercial
A supercut of all the DeviantArt of Vivi and Lewis living happily ever after
A supercut of all the DeviantArt of Arthur and Lewis living happily ever after!
Another Arthur x Lewis vid, marred by pans over the artwork and no accreditation
Supercut of just Lewis art (panned like crazy, unfortunately)
A sharpie marker animation of the story with Arthur as the ghost
The "Drive Over Me" fan animation
Ghost PMV!!!!
Ghost multi-fandom music video!
Ghost North West Mansion (Gravity Falls) music video


8-bit versions of the song:
Best 8-bit version
2nd 8-bit version
A warbly 8-bit version
3rd 8-bit version

Live versions:

Wikis and Blogs:
MysteryBen27's own awesome blog
A pretty good explanation of the story of the Mystery Skulls Wiki (pretty much the only useful thing on it)
The remarkably complete and well-researched entry for Ghost on Know Your Meme
Mystery Skulls' dry Wikipedia entry



Update 1/7/2017: People are going crazy reanimating the orginal "Money " video now:

Cute 8-bit rendering of the song with matching animation:

https://m.youtube.com/watch?v=7k0d7XttZVQ

Horrible "Live action" version:

https://m.youtube.com/watch?v=EILLyj85gcQ

Pony version!!! (Sadly a never-to-be-finished teaser:

https://m.youtube.com/watch?v=TqjHsb0KI3M

A slighly less good parody:

https://m.youtube.com/watch?v=CY4aTRMm3gU

A Holy Shit great recreation of the Turntable Turnabout video in a MMD, sadly just partial:

https://m.youtube.com/watch?v=kmlksBLN95I

Another MMD, longer and with a couple of funny in-jokes but the lack of synchonization to the rhythm is bothersome:

https://m.youtube.com/watch?v=jcfeB2NGeOM


Here's a couple of Nightcores of Money:

https://m.youtube.com/watch?v=ZBHG66uc07U

https://m.youtube.com/watch?v=AoElKLvCTQM

A super fast Nightcore with the Turntable Turnabout animation sped up to match:

https://m.youtube.com/watch?v=2Q0bKqWBP3I

Lastly, on top of all this, there are dozens of weird Korean or Japanese links, including one of the Nightcore video:

https://m.youtube.com/watch?v=o6GWxB42Z3s