sandromaffiodo.com
/homepage /list +nerd

Contact: yt tw fb in mail git


Posts: [all] terminal ebook epub arduino esp8266 espvgax vgax game javascript php scifi obfuscated ioccc piano music book youtube curl

Read EPUB from Terminal

ebookalice

The REAL Nerd do not use an EBook Reader. Use Terminal Emulators ONLY! :-D

EPUB file are easy to read. Technically an EPUB file is a ZIP file with containing a bunch on HTML files. So, it is pretty simple to read an EPUB using LYNX or W3M (terminal based browsers).

Using LYNX

unzip -l -p MY_EPUB_FILENAME text/* | lynx --stdin

Using W3M

unzip -l -p MY_EPUB_FILENAME text/* | w3m -T text/html

BASH Functions

Save this functions inside your .bashrc or .bash_profile file and you will have a persistent terminal command function to be used to read your lovely loved ebooks:


#read ebook with lynx
function epubl {
    unzip -l -p "$1" text/* | lynx --stdin
}
#read ebook with w3m
function epubw {
    unzip -l -p "$1" text/* | w3m -T text/html
}

Have FUN!

Piano from Terminal

I'm learning to play Piano but my terminal call me.. What about a simple piano visualizer in the terminal?

I need a simple visualizer that highlights piano keys.. I don't need it, really, but its fun to make everythings in the terminal (or not?). This visualizer looks like this:

Piano Screenshot

Coding

I have tried to write this tool with a "simple" bash script but i know C and i am more "productive" with C. So this is the main structure of the program:

/*p[Y][NOTE]
    where p[0] is the top line of the piano
          p[1] is the middle line of the piano
          p[2] is the bottom line of the piano
    foreach p[COLUMN] there are 14 keys for each OCTAVE
        [0] is the C key
        [1] is the C# key
        [2] is the D key
        [3] is the D# key
        [4] is the E key
        [5] is a dummy key for a not existent semitone
        [6] is the F key
        ...
        [12] is the A# key
        [13] is a dummy key for a not existent semitone 
        */
char p[3][14*N_OCT]={0};

//[...]
int main(int argc, char *argv[]) {
    //check argv for arguments

    //for each note in arguments hightlight p[0..2][NOTE]

    //draw all piano keys
}

The trick of using 14 keys instead of the standard 12 is used to calculate a key index, trought octaves, in a simpler way, assuming that each tone has a semitone. This is not true for E-F and B-C intervals but the program will intercept this exceptions and skip the [5] and the [13] dummy keys (not existent semitones).

This is how this trick work:

1) Notes are translated to numbers:

Notes: CDEFGAB
NOTE_INDEX: C=0 D=2 E=4 F=6 G=8 A=10 B=12

2) This formula is used to find the index of a key for a note without alterations:

KEY_INDEX = NOTE_INDEX(NOTE)*2 + (14 * OCTAVE)

3) (optional) code to add a semitone to a KEY_INDEX:

ALTERATED_KEY_INDEX: KEY_INDEX +1
IF (ALTERATED_KEY_INDEX==5 OR 13)
    ALTERATED_KEY_INDEX = ALTERATED_KEY_INDEX +1;

4) (optional) code to add two semitones (##):

two time the first algorithm

5) (optional) code to subtract a semitone (b):

one time the first algorithm with -1 instead of +1

6) (optional) code to subtract two semitones (bb):

two time the subtract of a single semitone

By using The trick of 14 keys, instead of 12, the program is pretty simple. For each note (ex: A2#) passed as an argument, the program will highlight the key using Terminal colors. After highlights of all keys the program draw all 12 keys (skipping the 5 and the 13 dummy keys).

Sourcecode

The full source of this program is here. The program use ANSI ESCAPE CODE to colorize the terminal output, so will run fine on a Linux machine, on Mac OS X or with MinGW on Windows.

Compile

To compile this program you do not need any fancy arguments:

gcc piano.c -o piano

Usage

This program accept a list of notes where each note syntax is

NOTE[OCTAVE][ALTERATION][ALTERATION]

For example if you want to highlight a C# you write C# (or B), if you want a C# on the second octave you write C2# (or B2), if you want a C with two semitones alteration you write C## (or B#).

By default the program will display 3 octaves but you can change that by using the -o (or --octaves) parameters.

The maximum number of octaves supported by the program is 10. You can extend this values by modifing the sourcecode, changing the value of the N_OCT macro.

Ok, this tool is useless... but exists :-D

YouTube from Terminal (Part 2)

This is the second part of the Nerd guide to play Youtube videos from your terminal.

In the first part these bash function has been added to my .bashrc (or .bash_profile on Mac OS X):

function yt {
    mpv --ontop --geometry=320x200+0+0 $(youtube-dl -g -f 18 $1)    
}
#download Youtube video using youtube-dl
function dyt {
    curl $(youtube-dl -g -f 18 $1) -o video.mp4
}

Now, the missing part is to search something and play all results. The follow solution will play all results in sequence. Youtube results are paginated on multiple HTML pages. In this case this script will play only the first page of results (who care.. these NERD scripts are insane):

#search Youtube and play all results
function yts {
    curl "https://www.youtube.com/results?search_query=$(echo $* | sed -E 's/ /%20/g')" -L | grep -o '/watch?[^\"]*' | uniq | grep -v "list=" | while read -r line; do yt "https://www.youtube.com$line"; done;
}

To use this function you only need only to type

yts MY LONG SEARCH STRING

To skip a video that you do not like you need to close mpv window. To terminate the script (looping throught all results) you need to send CTRL-C to the terminal running yts.

If you want to download all files, instead of playing them, you can use dyt instead of yt.

Let's break this function in pieces:

$(echo '$*' | sed -E 's/ /%20/g')

Grab all parameters passed to yts function ($*) and replace all whitespaces with %20 (the space character encoded for HTML URL)

curl "https://www.youtube.com/results?search_query=$(echo '$*' | sed -E 's/ /%20/g')" -L

Download youtube search results, following HTTP redirection (-L)

grep -o '/watch?[^\"]*' | uniq

Extract all /watch?* video URL. Some URL are duplicated so with uniq the output of the command is a list of unique URLs without duplicates

grep -v "list="

Exclude all lines that contains "list="; these lines are for Youtube playlists

while read -r line; do yt "https://www.youtube.com$line"; done;

Loop throught each line. For each line execute yt function to view the video (or dyt if you want to download videos).

Full code for play and search

#play Youtube video using youtube-dl
function yt {
    mpv --ontop --geometry=320x200+0+0 $(youtube-dl -g -f 18 $1)    
}
#download Youtube video using youtube-dl
function dyt {
    curl $(youtube-dl -g -f 18 $1) -o video.mp4
}
#search Youtube and play all results
function yts {
    curl "https://www.youtube.com/results?search_query=$(echo '$*' | sed -E 's/ /%20/g')" -L | grep -o '/watch?[^\"]*' | uniq | grep -v "list=" | while read -r line; do dyt "https://www.youtube.com$line"; done;
}

YouTube from Terminal (Part 1)

Sometimes a NERD watch Youtube without a browser opened. NERDS use text browsers like LYNX or W3M :-D

In the past years i've tryed mps-youtube and youtube-viewer, both are terminal apps that allow you to search, view and download videos from Youtube, but this time i want something more customizable, also based on youtube-dl.

Solution 1: play video from URL

You need only these two tools: youtube-dl and mpv. I think that these are the same tools used by mps-youtube. This solution is quick and dirty.

Installation on Mac (via brew) is easy:

brew install youtube-dl mpv

On Linux, Debian based distros, you can use apt:

apt-get install youtube-dl mpv

After that you can open your video with this command (replace VIDEO_URL with your Youtube video URL):

mpv $(youtube-dl -g -f 18 VIDEO_URL)

The magic number 18 is to select MP4 360p videos. If you want to select others format you can choose from one of these:

MAGIC NUMBER FORMAT RESOLUTION CODECS
171 webm audio only vorbis
140 m4a audio only mp4a
133 mp4 426x240 avc1 video only
134 mp4 640x360 avc1 video only
135 mp4 854x480 avc1 video only
247 webm 1280x720 vp9 video only
136 mp4 1280x720 avc1 video only
248 webm 1920x1080 vp9 video only
137 mp4 1920x1080 avc1 video only
43 webm 640x360 vp8 + vorbis
18 mp4 640x360 avc1 + mp4a
22 mp4 1280x720 avc1 + mp4a

If you want to be lazy in typing commands (like a real NERD needs to be), you can add this function to your .bashrc (or .bash_profile if you use Mac OS X) and use have this solution ready anytime you need to watch videos from terminal:

function yt {
    mpv $(youtube-dl -g -f 18 $1)   
} 

To use this function you only need only to type

yt VIDEO_URL

Download videos

If you want to download videos, instead of playing them, you only need to replace mpv with curl:

function dyt {
    curl $(youtube-dl -g -f 18 $1) -o video.mp4
} 

Picture in Picture alike

When i work on my computer i like to have the video that i am watching on one corner of the screen, possibly on top of the others windows (this mode is normally called PIP: picture in picture). With mpv you can use two parameters to configure the position of the window and the stay-on-top mode:

mpv --ontop --geometry=WIDTHxHEIGHT+X+Y

Add these parameters to your scripts to have mpv play like a PIP!

Experiment without youtube-dl (little more complex)

You don't like to use existent tools. You are a NERD and you like to do everything with a bunch of curl, grep and sed commands. Supposing that you do not wont to rewrite curl or mpv (you dont?), you can use curl to extract the required video URL and play that with mpv:

function ytc {
    mpv $(echo -ne $(curl $1 | grep -o 'https[^\"]*' | grep videoplayback | grep itag%3D18 | sed -E "s/%/\\\\x/g"))
}

This is it. HTML scraping: the worst thing you should do, EVER. Let's break each command apart:

curl $1 | grep -o 'https[^\"]*'

curl youtube page and extract all HTTPS links contained in the page. If you look at the HTML page returned from Youtube, you will see that inside HTML there is a big JSON string that contains all HTTPS URLs for the final video playback. These links contains the videoplayback substring. see screenshot-1

grep videoplayback

select only lines that contains videoplayback substring

grep itag%3D18

select only lines with itag=18 (my preferred format is 18, you can choose others format from the table above). %3D is the character = escaped inside the HTTP URL

sed -E "s/%/\\\\x/g"

convert each HTTP encoded characters from %NN to \xNN. This is the standard C/bash escape for characters expressed as hexadecimal two digit number

echo -ne

echo results converting all \xNN sequences to its ASCII equivalents. After that you obtain the final URL. Something like this: r11---sn-hpa7zn7r.googlevideo.com/videoplayback?initcwndbps=472500&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&ip=87.8.231.48&key=yt6&mn=sn-hpa7zn7r&signature=23D980F8415F6F313EF422E95BA85AA55FCD22BA.96645A049DC436870F36DD48BFE64DE20283F787&mm=31&ms=au&id=o-AP4my72PmmcNCaYptxcQ92Q3knmzotCfM9FaAHfHAW5E&ei=PAw6WP2GE4HXcPy_haAF&mv=m&mt=1480198892&dur=590.483&lmt=1428034888381069&source=youtube&upn=vncEZvHsRZc&itag=18&requiressl=yes&clen=40049035&nh=IgpwcjA0Lm1pbDAxKgw3Mi4xNC4yMDQuNzM&ipbits=0&ratebypass=yes&pl=19&expire=1480220828&gir=yes&mime=video%2Fmp4

mpv

run mpv, finally

PLEASE NOTE that this solution do not work for all Youtube videos. Use youtube-dl instead, it works better and it is less insane.

Full code

#play Youtube video using youtube-dl
function yt {
    mpv --ontop --geometry=320x200+0+0 $(youtube-dl -g -f 18 $1)    
}
#download Youtube video using youtube-dl
function dyt {
    curl $(youtube-dl -g -f 18 $1) -o video.mp4
}
#play Youtube video without youtube-dl (do not work for all videos) 
function ytc {
    mpv $(echo -ne $(curl $1 | grep -o 'https[^\"]*' | grep videoplayback | grep itag%3D18 | sed -E "s/%/\\\\x/g"))
}
#download Youtube video without youtube-dl (do not work for all videos) 
function ytc {
    curl $(echo -ne $(curl $1 | grep -o 'https[^\"]*' | grep videoplayback | grep itag%3D18 | sed -E "s/%/\\\\x/g")) -o video.mp4
}

Have FUN (or use a normal, more easy, soft clickable, quite adorable WebBrowser like everyone do)