_\~ /\ |\| |) /? () |\/| /\ /= /= | () |) ()
/homepage /list +normal

Contact: yt tw fb in mail git


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

VGAX Support for ATMega2560

I've added support for ATMega2560 to my library VGAX! Now the library can be configured to generate 120x90px (with squared pixels) or 120x240px (rectangular pixels).

atmega2560-video1

Video of VGAX on ATMega2560

The wiring is simple, like for ATMega328. You can wire up an Arduino MEGA board with some cheap components:

atmega2560-1

To enable 120x90px resolution you need to uncomment the constant ATMEGA2560_HIGHRES on VGAX.h header. To enable 120x240px uncomment ATMEGA2560_MAXRES.

The tricky part to add support for ATMega2560 has been adapting the interrupt dejitter code. I've found that the original code, writen by Charles CNLOHR assume to work on an AVR MCU with a 16bit Program Counter. ATMega2560, like others fat MCU, has a 22bit Program Counter! So, when Charles pop PC from stack, code must be modified to pop 3 bytes instead of 2 (22bit PC requires 3 bytes):

#define DEJITTER_OFFSET 1
#define DEJITTER_SYNC -2
asm volatile(
  "     lds r16, %[timer0]    \n\t" //
  #if defined(__AVR_ATmega2560__)
  "     add r16, %[toffset]   \n\t" //
  #endif
  "     subi r16, %[tsync]    \n\t" //
  "     andi r16, 7           \n\t" //
  "     call TL               \n\t" //
  "TL:                        \n\t" //
  #if defined(__AVR_ATmega2560__)
  "     pop r17               \n\t" //ATMEGA2560 has a 22bit PC!
  #endif
  "     pop r31               \n\t" //
  "     pop r30               \n\t" //
  "     adiw r30, (LW-TL-5)   \n\t" //
  "     add r30, r16          \n\t" //
  //"   adc r31, __zero_reg__ \n\t" //
  "     ijmp                  \n\t" //
  "LW:                        \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  "     nop                   \n\t" //
  //"   nop                   \n\t" //
  "LBEND:                     \n\t" //
:
: [timer0] "i" (&TCNT0),
  [toffset] "i" ((uint8_t)DEJITTER_OFFSET),
  [tsync] "i" ((uint8_t)DEJITTER_SYNC)
: "r30", "r31", "r16", "r17");

MCU PORTD must be changed to PORTA becouse PORTD does not have 8 pins, so all the assumptions made in VGAX for ATMega328 cannot work with PORTD for ATMega2560. Colors pins must be moved from pin 6 and pin 7 to pin 30 and pin 31 (higher 2 bits of PORTA in ATMega2560).

TIMER0 setup must be also modified to work fine on both ATMega328 and ATMega2560.

That's all! :)

ATMega2560 has 8KB of SRAM, more space for framebuffer to increase vertical resolution from 60 to 90 or 240px. In theory with ATMega2560 a new library can be created to use 256 colors (with RRRGGGBB pixel format) or 16 colors (RGBH-RGBH double pixels in single byte format). I think to try to write, in the future, these variations of VGAX inside new differents libraries (VGAX256 and VGAX16 ?).

Have fun!

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!

Arduino ESPVGAX Library

This is a VGA Arduino library for ESP8266. It can display a 512x480 image with 1bit per pixel.

espvgax-0

Here you can download the Library code from GitHub. It's free and opensource.

Wiring

Like my VGAX Library, this Library require cheap components. You can generate a signal from an ESP8266 with less then 5$ :-)

ESPVGAX require a DSUB15 connector (aka VGA connector) and one 330Ohm resistor:

espvgax-2

Super simple!

Colors combinations

espvgax-1

You can wire the VGA connector in some different modes that allow you to choose your preferred white color. For example you can choose to wire it up to use black and green colors, or black and purple.

espvgax-3

You can find more informations about colors combinations here.

Additional colors

The Library also support two modes where colors can be increased from the standard 2 colors.

espvgax-1

The first additional mode allow you to hook up an hardware PIN to one of the VGA pins (different from the primary color that you have selected in the first wiring). Thi hardware PIN is always ON when VGA signal pixeldata is generated, so you can change the background color from black to another color. This change is permanent and you cannot turn ON/OFF this background color variation.

espvgax-3

The idea behind the second additional mode is this: ESP8266 HSPI can send data to VGA as a serial stream of bits, so it can only turn one VGA PIN ON/OFF at a time. But VGA timing has gaps between lines that can allow more code to be executed, before and after sending the stream of bits. So, before sending the data, the Library can turn ON/OFF some other bits and change the color combination used in each horizontal line (480 lines).

espvgax-3

The VGA signals can become unstable if your code uses Wifi, Serial, and other Arduino classes. You can find more informations here.

ESPVGAX on GitHub

Happy Hacking!

Arduino BITNINJA

This is my first game for VGAX the VGA library that i have developed for Arduino.

bitninja-1

TLDR: Video of BITNINJA first test

The game

This game is a small platform game, like Super Mario Bros, designed by me. After my nomination in the IOCCC 2014 Contest, i have ported some of the logic of the SMB Engine that i have developed for the Contest.

bitninja-2

BITNINJA implements these features:

RAM Optimizations

Becouse VGAX uses 1800 bytes of RAM and the Arduino UNO ATMEGA328 MCU has only 2048 bytes of RAM, the game is optimized to use only 41 bytes of global RAM. All the images, sprites, songs and level definitions are stored in the MCU FLASH ROM. Doing the math: 2048-1800-41=207 bytes are "free", used for the MCU STACK where local variables and parameters are stored.

The 41 bytes required for BITNINJA to run are subdivided like this:

Sourcecode

Here you can download the BITNINJA source code !

Hardware

The hardware required is pretty cheap:

The wiring and soldering is documented inside VGAX library documentation, except for the wiring of the standalone ATMEGA328 MCU but you can easily find online How to run ATMEGA328 standalone.

bitninja-3

bitninja-4

Here you can see a video of BITNINJA testing running on the Arduino UNO, before the standalone board creation. The level you see in the video is a test. The 5 levels inside the final version are different than the one in the video.

This is the final board, with a piece of plexi on the bottom:

bitninja-5

bitninja-6

I am planning to take a video of all 5 levels, running on the final standalone board. When i will do the video i will post it here!

Have FUN!

Arduino Robot UNO

This is my first Arduino Robot, created in 2011!

robotuno-IMG0

The idea

The reason i have build it is that i need to control my audio system volume knob without phisically stand up, walk and turn the knob. I am laaazy :-D

I have a TV Remote with volume controls (and mute button) and i want to use the TV Remote to rotate the volume knob.

TLDR: Making of Arduino ROBOT UNO on Youtube!

My audio system is a Creative INSPIRE Audio 4+1 Surround System that i has originally bought for my old PC. It has a volume knob to control its volume level by hand:

creative

Hardware and Software

I have started this project by creating a tape/cardboard prototype with an Arduino UNO board, using a servo motor and an infrared receiver. Then, after some tests, i have started to modify the code so it can run on an ATTINY85 MCU, smaller than the ATMEGA328 MCU used by Arduino UNO:

robotuno-IMG5

I have used the Arduino UNO board to program the ATTINY85 MCU, using an online tutorial like this. Note that ATTINY85, like ATMEGA328, has an internal oscillator that can generate the MCU clock at 8Mhz or 1Mhz, so you don't need an external oscillator (or quartz) to power the MCU. In my Arduino Robot UNO i have choose to run at 8Mhz.

robotuno-IMG4

After that i have build the minimal circuit for the "brain" of the robot. The servo motor will be installed as one of the robot hands.

robotuno-IMG1

CNC cutting

I own a small CNC router that can be controlled via GCODE. At this point i have designed some sheets of plastic parts to be cutted and glued together to become the outer aspect of the robot.

robotuno-CNC

.. then i cut everythings with the CNC router ..

robotuno-IMG2

.. and glued all pieces together!

robotuno-IMG3

Here you can see the Making of Arduino ROBOT UNO, step by step.

After some weeks of testings i have notice that the batteries life was too short (3 AAA for week), so i have modified the hardware to get the 5V power from a cellular power supply. Now ROBOT UNO has a cable that go out from its head and connect to a 5V microUSB connector to the power supply.. :-D

Here you can download the Arduino ROBOT UNO sourcecode.

Design note

The ROBOT UNO design is inspired from my childhood best robot film: Short Circuit!

jhonny5

Long live Jhonny Five! Inpuuuut, MORE INPUT

Arduino Rubik Server

rubik-1

This was my first Arduino project: A webserver inside a Rubik's cube (2x2x2 Pocket Cube version) able to solve a Rubik's Cube 3x3x3 with the Layer-by-Layer method. It is fast! Can solve any scramble in around 100msec, using only 2048 bytes of RAM (ATMEGA328 MCU)!

Coding

I am a Rubik's Cube fan. I learned how to solve the 3x3x3 standard Rubik's Cube by following this guide. But i does not follow all raccomandations and learned to solve it creating a first RED CROSS instead of WHITE CROSS.

As a programmer i have developed a simple solver in Javascript that can solve the 3x3x3 cube by using the Layer by Layer method, starting from the RED CROSS. The project was developed using Javascript, HTML5, Canvas and WebGL.

Here you can find the Smaffer 3D Cube project homepage.

After that, for the IOCCC Contest, i have ported the Javascript solver to C with some obfuscations to follow the rules of the contest.

As an Arduino fan i have also ported the obfuscated code to C++, optimizing it to use the lower amount of RAM possible, without rewriting all the code. The source code is not simple to understand.. its obfuscated.. but it works. Can solve a 3x3x3 using a standard scramble sequence.

Hardware time

The hardware required to create this project is this:

rubik-2

I have used the ENC28j60 breakout board to connect the Arduino ATMEGA328 MCU to Ethernet. The cube parts are from a broken 2x2x2 Pocket Cube given to me by EFFEOTTO (thanks!).

Running page

The Arduino WebServer hosted by the MCU has a simple NERDY style:

rubik-3

You can send the scramble sequence inside the HTTP URL. The returned page will contains the scrambled 3x3x3 cube and the list of moves to solve it.

Solving modes

The sourcecode can solve the cube in two modes: with cube rotations moves (X, Y, Z) or without rotations (in place solving). The second mode can be used, theoretically, to solve the cube phisically, using hardware motors, without full rotations of the cube (the cube stay always in the same original orientation).

Wiring mess

This was my first Arduino project and this fact can be seen in the internal hardware soldering and wiring. But the final cube works and i think that the idea is fun and so nerdy! :-P

rubik-6

rubik-5

rubik-4

Problems

The big problem with this project, after some tests, is the battery. The idea to power up the cube using a 9V battery is not happy. The power consumption of the Ethernet connection is very high and the cube, powered with a fully charged 9V battery, cannot stay ON more than a couple of hours :-/

Future and Download

In the future, i will do a porting of this project to ESP8266, powered by a microUSB connector.

That's IT!

Here you can download the Arduino Sketch sourcecode. It is a porting of an obfuscated program so it is not simple to understand at all.. :-/

Happy hacking

1981 The Game

1981

This is a SciFi text game, written by me. A text game is like the old "Libro Game" that i read in my childhood (80s). You can read the story and choose how the story must continue.

1981 is short, you can complete the story in 15 minutes but warning: there are more than one ending!! :-)

Here you can play 1981 The Game. NOTE: The game is written in italian! There is no translation in any other languages!

1981 was written in Javascript, PHP and CSS3!

I am planning to upgrade the 1981 website to be Responsive and Mobile Friendly but i don't know when i can do this.. in the future, sure.

Some years ago i have started to porting this game to an Arduino projects... but i never complete the project.. yet!

This game was originally published on the ASSEZETA.COM website, created by me and my old friend Marco Baudino.

Arduino VGAX Library

vgaxA0

When i have bought my first Arduino UNO i have started to test some libraries for video signal generation. One of the first interesting library was TVOut. A simple lib that allow you to generate a COMPOSITE video signal out of an ATMEGA328 MCU, using only some resistors and a COMPOSITE video connector.

VGAX Inspirations

The first inspiration for VGAX come from TVOut library: A simple VGA library for Arduino that can work with simple cheap components!

Online i have found some interesting articles about Arduino VGA video signal generation, written by Nick Gammon. These articles and his works was the starting point for the development of my VGAX Library.

vgaxA0

My writing of VGAX was also inspired by the work of Petri Häkkinen, creator of the game TORUM QUEST II (for ATMEGA328!!). Here a link to his Blog. Here a link to his post on the Arduino Forum.

torum-quest Youtube Video

VGAX Assembler core

The creation of VGAX was a little tricky. I've spent many nights around the interrupt jitter problem, trying to adjust some dejitter code founds online.. An Hell!

To write the Assembler core of VGAX i've studied the official ATMEL ATMEGA328 Instruction Set Manual (190 pages), searching for the best instructions to generate the PIXEL stream output without losing too many CPU cycles. The idea was to use these instructions, for each byte of the framebuffer, inside an unrolled loop

.rept 30             // output 4 pixels (unrolled loop)
    ld r16, Z+       
    out %[port], r16 // write pixel 1 
    mul r16, r20     // left shift 2
    out %[port], r0  // write pixel 2
    mul r0, r20      // left shift 2
    out %[port], r0  // write pixel 3
    mul r0, r20      // left shift 2
    out %[port], r0  // write pixel 4
.endr                

The first good thing is that LD and MUL instructions require both 2 CPU cycles, so the output of the four pixels, packed inside a single byte, is done with the same number of CPU cycles for each pixel (3 cycles, LD=2, MUL=2, OUT=1). This equal timing ensures that all generated pixels will be displayed with the same size (horizontal width).

The second tricky thing is that the two VGA PINs are written with a single OUT instruction that writes an 8bits hardware PORT... but bits cannot be rearranged without losing time.. so the idea was to (pre)arrange the 4 pixels in one byte keeping the order of the bits aligned to the output pins of the 8BIT PORT. First pixel is stored in the higher 2 bits of byte.

pixel-packing

The hardware PORT uses the PIN from 0 to 7 so i have wired the two VGA PINs to PIN6 and PIN7.

PORT-wiring

When a byte is read from the LD instruction, the first pixel bits are already on the 6th and 7th bits, ready to be written out from the OUT instruction. The next MUL will shift the second pixel bits to the right position (6th and 7th bits of the PORT) and written out. This is repeated for the remaining two pixels.

ld r16, Z+       
out %[port], r16 // pixel1 bits are aligned on PORT 6th and 7th bits
mul r16, r20     // shift 2 pixel up
out %[port], r0  // pixel2 bits are now aligned

Resolution limitations

Many people ask me if is possible to increase the horizontal resolution of the VGA signal (120px).

Arduino ATMEGA328 has only 2048 bytes of RAM! The VGAX framebuffer have a resolution of 120x60px with 2bpp, almost all the MCU RAM is used (1800 bytes). This is the first limitation that cannot allow an increase of the horizontal resolution without losing color depth (2bpp). But there is another important reason that does not allow a greater horizontal resolution: the CPU speed!

ATMEGA328, inside Arduino, runs at 16Mhz. VGA signal require a 25Mhz PIXEL output speed. If you calculate the number of CPU cycles used to send PIXEL out you obtain this formula:

25Mhz : 640px = (16Mhz / 3clocks) : RES
RES = (640 * 5.3) / 25
RES = 136px~

So, the maximum resolution possible, at 16Mhz, using 3 CPU cycles for each pixel, is 136px! VGAX for ATMEGA328, with the dejitter code and the audio signal generation, reach a resolution of 120px for each horizontal line, near the maximum resolution possible.

Sharing

Here is hosted my VGAX Library, on GitHub. Here my post on the Arduino Forum.

This library was used from some people around the world. I thanks everybody for have spent some time using VGAX! Many thanks to Rob Cai that has recreated some classic games like Tetris, Pong and Breakout, using VGAX!

ct make

VGAX was reviewed in an article of the C'T MAKE newspaper, number of 03/2017. When i read this article i am always happy! :-)

MINICHIP The Game

A little platform game programmed in Javascript. This was the origin for the development of my future IOCCC Super Mario Bros Platform Engine. All the graphics (in pixelart) and sounds are created by me. This game has also a simple Level Editor i have used to design all levels of the game.

minichip0

This game was originally hosted on ASSEZETA.COM, years ago.

Here you can open the MINICHIP Homepage.

Following are some of the sprites used inside the game:

player

enemy-1

power-ups

robots

Have FUN!

IOCCC 2014 Winning entries

Long time ago (2014), in a galaxy far far away, i have won two nominations at the Internatonal Obfuscated Code Contest. I remember when I discovered the IOCCC, back in 2003, thanks to EFFEOTTO ... I would have never thought to participate and win something .. but in a single year i have won two times! Incredible :-)

Homage to a classic game

This is the source code of the first winning entry:

obfuscated-program

The program is not only a Super Mario Bros partial implementation but also a generic Engine for Platform Games. It can be used to create games like Super Mario Bros. The contest entry was released with two example games level: one level of Super Mario Bros and one level of Giana the Sister (an SMB-like game for Amiga).

These are two screenshots of the two playable levels:

super-mario-bros

giana-the-sister

The Engine implements all the needed stuff:

These are the IOCCC Selected Judges Remarks about this program:

"A classic for a particular generation. Like all good programs, being data driven means you can do fun things in small spaces."

Here you can download the obfuscated sourcecode. If you open the file with and see some ugly alignment, set the TAB WIDTH of your text editor equal to 4. :-)

Here you can download the not obfuscated sourcecode. The code is already unreadable due to the shrink in sizes and due to the multiple rewrite steps (needed to simplify all the internal logic of the Engine).

Here you can read the official IOCCC winning entry description.

Most tweetable entry

The second winning entry is very little. This is the program full sourcecode:

d=80,e,j;g(){j+=getchar();}main(a,b)char**b;{for(;;){j=0;g();if(j<0)break;g(g());putchar(b[1][j/3*strlen(b[1])>>8]);if(!(++e%d))puts("");}}

There is also a shortest version of the same program, with a simplified logic:

d=80,e,j;g(){j+=getchar();}main(){for(;;){j=0;g();if(j<0)break;g(g());putchar(" .:#@"[j/3*5>>8]);if(!(++e%d))puts("");}}

What the hell do the program do?

monna-lisa

The program convert the image given in input to an ASCII ART!

These are the IOCCC Selected Judges Remarks about this program:

"On the face of it :-) given what this program one might wonder what makes this winner special. But when you realize the source is small enough to tweet on twitter you understand.

Who will be the first to tweet this source? How many re-tweets will such tweet get? And how many people will really understand the tweet?"

Here you can read the official IOCCC winning entry description.

...

Now... Really... How much is insanely NERD all of this?

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

THEY'RE MADE OUT OF MEAT

I always love to read this short story about "Humans":

"They're made out of meat."

"Meat?"

"Meat. They're made out of meat."

"Meat?"

"There's no doubt about it. We picked up several from different parts of the planet, took them aboard our recon vessels, and probed them all the way through. They're completely meat."

"That's impossible. What about the radio signals? The messages to the stars?"

"They use the radio waves to talk, but the signals don't come from them. The signals come from machines."

"So who made the machines? That's who we want to contact."

"They made the machines. That's what I'm trying to tell you. Meat made the machines."

"That's ridiculous. How can meat make a machine? You're asking me to believe in sentient meat."

"I'm not asking you, I'm telling you. These creatures are the only sentient race in that sector and they're made out of meat."

... continue here.

Author: Terry_Bisson

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)