Sunday, July 9, 2017

Youtube Downloader - Ta ta ta ta da DAAAAA! PUPPY POWER!

God Bless YouTube!

Where else can you find entertainment, education and countless kitty/puppy videos?

But what if you wish to preserve the video, downloading for archive purposes or access it from Internet-incapable devices?

Start by installing youtube-dl:
$ sudo apt-get install youtube-dl

Next, navigate to your desired video and copy the URL; e.g.

http://www.youtube.com/watch?v=Wtfo43yV8rA

Lastly, execute youtube-dl with specified URL:

$ youtube-dl http://www.youtube.com/watch?v=Wtfo43yV8rA

The result will be a Macromedia Flash Video file.  Convert to your preferred file format using Ffmeg and Bob's Your Uncle.

Monday, July 3, 2017

Trello -- Get Your Scrum On

For more than a year I was on the receiving end of 'why is your scrumboard not electronic' line of questioning from my team, my leadership, my customers and pretty much anyone else who had an opinion on the matter.

Our scrum room looked like this:

Despite making my living utilizing tech, it proved difficult to defend the 'old school' post-its and whiteboards.  There were a few things that compelled me to keep my distance from Agile tool sets.  For those of you that utilize more sophisticated tool chains, good on ya and I'm not implying there is anything wrong with them.

Licensing costs, risk of loss of proprietary information in cloud-based systems, feature sets that I trust we'd never use (e.g. burn-down charts and metrics) and most importantly I personally felt the  satisfaction of disclosing your task completion and physically moving a task from 'in progress' to 'complete' with a sense of accomplishment.  My resistance was reinforced when participating in sprints led by other scrum masters that used 'MS Excel' (I know, wrong tool) and the tone of the meeting became more a status meeting than a scrum.

I yearned for a scrum room with a wall-sized electronic smart board; electronic equivalent of post-its and baby, Trello is pretty close to what I wanted.

Free to use, flexible, and pretty much what the doctor ordered.  I invite you to take a look.  I've found myself using it at work, home and play and use it from such mundane tasks as packing luggage items to coordinating my blog backlog.


Take a peak, you'll be glad you did.

http://trello.com

Monday, June 26, 2017

GDB-QuickStart -- 'Things That Make You Go Hmm'

Seems over the years I find myself in and out of using a debugger.  Largely driven by the system and tools available, sometimes the use of a debugger is essential, other times a reliance on debug logs is the way to go.

I found myself back into the GDB thick of things over the past couple weeks, shaking off a good deal of GDB rust.  I figured a worthwhile effort would be to document a quick re-introduction, by no means intended on being exhaustive but a starting point for potentially follow-on posts.

Let's start with the simplest of examples, a single source file consisting of a series of functions making up a call stack;

Let's start with a simple main source file;
$ cat main.cpp
#include <stdio.h>

void function05()
{
  printf("(%s:%d) function05()\n",__FILE__,__LINE__);
}

void function04()
{
  printf("(%s:%d) function04()\n",__FILE__,__LINE__);
  function05();
}

void function03()
{
  printf("(%s:%d) function03()\n",__FILE__,__LINE__);
  function04();
}

void function02()
{
  printf("(%s:%d) function02()\n",__FILE__,__LINE__);
  function03();
}

void function01()
{
  printf("(%s:%d) function01()\n",__FILE__,__LINE__);
  function02();
}

int main(int argc, char* argv[])
{
  printf("(%s:%d) main process initializing\n",__FILE__,__LINE__);
  function01();
  printf("(%s:%d) main process terminating\n",__FILE__,__LINE__);
}

Compile it with debugging symbols (e.g. '-g' g flag);
$ g -g -o3 main.cpp -o main
And now run the debugger with the executable; 1st listing all functions, then set a breakpoint on a couple function, followed by running the executable and continuing on after each encountered breakpoint;
$ gdb main
Reading symbols from main...done.
(gdb) info functions
All defined functions:

File main.cpp:
void function01();
void function02();
void function03();
void function04();
void function05();
int main(int, char**);

Non-debugging symbols:
0x00000000004003c8  _init
0x0000000000400400  printf@plt
0x0000000000400410  __libc_start_main@plt
0x0000000000400430  _start
(gdb) break main
Breakpoint 1 at 0x4005e9: file main.cpp, line 34.
(gdb) break function01
Breakpoint 2 at 0x4005b9: file main.cpp, line 28.
(gdb) run
Starting program: /home/lipeltgm/svn/mal/main/trunk/personal/lipeltgm/blog/Gdb-Qs/main 

Breakpoint 1, main (argc=1, argv=0x7fffffffdf18) at main.cpp:34
34  printf("(%s:%d) main process initializing\n",__FILE__,__LINE__);
(gdb) cont
Continuing.
(main.cpp:34) main process initializing

Breakpoint 2, function01 () at main.cpp:28
28  printf("(%s:%d) function01()\n",__FILE__,__LINE__);
(gdb) cont
Continuing.
(main.cpp:28) function01()
(main.cpp:22) function02()
(main.cpp:16) function03()
(main.cpp:10) function04()
(main.cpp:5) function05()
(main.cpp:36) main process terminating
[Inferior 1 (process 7371) exited normally]
(gdb) quit
$

Once all the symbol tables are loaded, the 'info functions' command may very well be your best friend.  For small and simple programs, sorting through a list of a dozen or so methods is easy pickings, but for more complex and larger programs you'll find it burden-some.  The 'info functions' allows specifying a regular expression to provide a filter for just such a reason.  Issuing a 'info functions function0' will show all functions that satisfy the 'function0' regular expression, namely the functions 'function01(), function02(), function03(), function04(), function05()'.  A regular expression can take the form of a namespace, a class, a function name,....and you'll likely find it one of the more useful functions at your disposal to make sure you're setting good breakpoints.
(gdb) info functions function0
All functions matching regular expression "function0":

File main.cpp:
void function01();
void function02();
void function03();
void function04();
void function05();
(gdb) 

Tip of the iceberg stuff here; refer to https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html for a more complete reference.
It may be good practice to get in the habit of establishing a breakpoint within the main function and establish your breakpoints and such after triggering the breakpoint.  While not necessary for statically linked executables, waiting to establish breakpoints after reaching the main function will work for static and run-time libraries and avoid 'pending breakpoints' which can be error-prone.  Let's look at the use of a run-time library to better demonstrate what I mean.
$ more MyClass.h MyClass.cpp
::::::::::::::
MyClass.h
::::::::::::::
#ifndef MYCLASS_H
#define MYCLASS_H
  class MyClass
  {
    public:
      MyClass();
      ~MyClass();
    private:
  };
#endif
::::::::::::::
MyClass.cpp
::::::::::::::
#include "MyClass.h"
#include <stdio.h>

MyClass::MyClass()
{
  printf("(%s:%d) constructor\n",__FILE__,__LINE__);
}

MyClass::~MyClass()
{
  printf("(%s:%d) destructor\n",__FILE__,__LINE__);
}

Create a shared library;
$ g  -g -o3 -fPIC  -c -o MyClass.o MyClass.cpp
$ g -shared MyClass.o -o libMyLib.so -fPIC -Wl,--whole-archive -Wl,--no-whole-archive 
$ g   mainRt.o libMyLib.so   -o mainRt

Attempts to run will meet you with an error of the fashion;
$ ./mainRt 
./mainRt: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory

Tell the shared library loader how to locate the libMyLib.so file and you're back in the saddle.
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
$ ./mainRt
(mainRt.cpp:6) main process initializing
(MyClass.cpp:6) constructor
(mainRt.cpp:8) main process terminating
(MyClass.cpp:11) destructor

Ok, fine, now we have a shared library and can run it, let's move on to the use of library in GDB.  Attempts to use the 'info functions' may fail, dependent on whether the libraries are loaded.  To insure the libraries are loaded a good practice is to set a breakpoint in main and establish the rest of the breakpoints after hitting it.
$ gdb mainRt
(gdb) break main
Breakpoint 1 at 0x4008b6: file mainRt.cpp, line 5.
(gdb) r
Starting program: /home/lipeltgm/svn/mal/main/trunk/personal/lipeltgm/blog/Gdb-Qs/mainRt 

Breakpoint 1, main (argc=1, argv=0x7fffffffdf18) at mainRt.cpp:5
5 {
(gdb) info functions MyClass
All functions matching regular expression "MyClass":

File MyClass.cpp:
void MyClass::MyClass();
void MyClass::~MyClass();

Non-debugging symbols:
0x0000000000400760  MyClass::~MyClass()@plt
0x0000000000400770  MyClass::MyClass()@plt
(gdb) rbreak MyClass
Breakpoint 2 at 0x7ffff7bd573c: file MyClass.cpp, line 6.
void MyClass::MyClass();
Breakpoint 3 at 0x7ffff7bd5768: file MyClass.cpp, line 11.
void MyClass::~MyClass();
Breakpoint 4 at 0x400760
<function, no debug info> MyClass::~MyClass()@plt;
Breakpoint 5 at 0x400770
<function, no debug info> MyClass::MyClass()@plt;
(gdb) cont
Continuing.
(mainRt.cpp:6) main process initializing

Breakpoint 5, 0x0000000000400770 in MyClass::MyClass()@plt ()
(gdb) cont
Continuing.

Breakpoint 2, MyClass::MyClass (this=0x7fffffffde17) at MyClass.cpp:6
6  printf("(%s:%d) constructor\n",__FILE__,__LINE__);
(gdb) cont
Continuing.
(MyClass.cpp:6) constructor
(mainRt.cpp:8) main process terminating

Breakpoint 4, 0x0000000000400760 in MyClass::~MyClass()@plt ()
(gdb) cont
Continuing.

Breakpoint 3, MyClass::~MyClass (this=0x7fffffffde17, 
    __in_chrg=<optimized out>) at MyClass.cpp:11
11  printf("(%s:%d) destructor\n",__FILE__,__LINE__);
(gdb) cont
Continuing.
(MyClass.cpp:11) destructor
[Inferior 1 (process 8191) exited normally]
(gdb) quit

Albeit just a starting point, but a starting point just the same.

Cheers.



Tuesday, April 25, 2017

FFMpeg Green Screen - A Chroma Key For Every Lock

Green screen effects are older than I am, by a significant margin.

The technique; essentially recording a subject in front of a uniformly colored screen, often green, then taking that recording figuratively making all the green background transparent and finally overlaying on another video.  The result, the subject filmed in from of the green screen appearing in the context of the second video.  Easiest and safest way to film your kids in a shark tank.

Before we get started, the majority of my FFMpeg posts use filters and capabilities that have existed in FFMpeg for quite some time (e.g. v2.7.2), but the chroma key filter is fairly new, I used v3.2.4, but I suspect the capability was introduced some time earlier.

There are a good deal of green screen videos available on YouTube for playing around.  Let's demonstrate how to generate a crude green screen.

Let's start with the green screen subject.

Then, let's look at a video we wish to introduce our subject into.


Sprinkle in a little FFMpeg magic;
Prior to overlaying the two videos, they need to be similar in size and framerate.
$ ffmpeg -n -i foreground.mp4 -ss 20 -t 120 -strict -2 -s hd720 -r 30 foreground-720p.mp4
$ ffmpeg -n -i background.mp4 -ss 20 -t 120 -strict -2 -s hd720 -r 30 background-720p.mp4

Then, specify the two videos, the color of the green screen and some blending factors.

$ ffmpeg -y -i background-720p.mp4 -i foreground-720p.mp4 -filter_complex '[1:v]colorkey=0x008000\:0.3\:0.2[ckout];[0:v][ckout]overlay[out]' -map '[out]' -t 10 greenScreen.mp4

The result:

Now, take your new skills and your own creativity and show the world your new-found powers!

Thursday, April 20, 2017

FFMpeg Fade Controls -- Fade to Black

A pretty common for the open scenes of a video to 'fade in' and 'fade out' at the ending of the video.  Ffmpeg provides a video filter to easily apply fading in/out, the subject of this post.  Saddle up and prepare to be amazed.

Let's start with a simple 30-second video as our input:

Fade In

The video fade-in filter is of the form fade=in:<startFrame><endFrame>, simply specifying a start and stop reference, the fading will begin at the start point and complete at the stop point.  The units, unfortunately, are frame numbers rather than time (e.g. seconds).

Given the video is 24 fps, we can fade into the video in the first 5 seconds by issuing the following command:
$ ffmpeg -y -i opening.mp4 -vf fade=in:0:120 -acodec copy fadeIn-5sec.mp4

Fading in the first 10 seconds by:
$ ffmpeg -y -i opening.mp4 -vf fade=in:0:240 -acodec copy fadeIn-10sec.mp4

Fading in the first 20 seconds by:
$ ffmpeg -y -i opening.mp4 -vf fade=in:0:480 -acodec copy fadeIn-20sec.mp4

Fade Out

The video fade-out filter is of the form fade=out:<startFrame><fade duration>, simply specifying a start and stop reference, the fading will begin at the start point and within the specified duration.  The units, unfortunately, are frames rather than time (e.g. seconds).

Fading out the last 10 seconds is a bit trickier, primarily because of the frame units.  In order to specify the start/duration references we need to know the number of frames in the video and the fps.

Frame count can be determined by:
$ ffprobe -v error -count_frames -select_streams v:0   -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1  opening.mp4
719
10sec = 240 frames

Starting reference would be 719-240 (24fps * 10sec) = 479:
$ ffmpeg -y -i opening.mp4 -vf fade=out:479:240 -acodec copy fadeOut-10sec.mp4

Fade In/Out

You can chain fade in and out affects, for instance to fade in the first 10 seconds and fade out the last 10 seconds:
$ ffmpeg -y -i opening.mp4 -vf fade=in:0:240,fade=out:479:240 -acodec copy fadeInOut.mp4

Now, go forth and use these tricks responsibly.

Cheers

Sunday, April 9, 2017

Video Ticker -- Give Your Text Some Legs

CNN does it, many videos with lyrics do it, why pray tell aren't you?

We'll explore the introduction of lyrics in future posts, but it's pretty common to overlay text onto a video.  Applying moving text is a bit less common, but easily do-able with a bit of tweaking and patience.

Let's take a simple video, a guaranteed ear wig:

Next, if we grab the lyrics and paste them into a text file; http://www.metrolyrics.com/dowackado-lyrics-roger-miller.html

We can overlay the contents of the lyrics file in the form of moving text by the following command:
$ ffmpeg -y -i video.mp4 -vf "drawtext=enable='gte(t,0)':fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:fontsize=36:fontcolor=white:borderw=5:textfile=lyrics.txt:reload=1:y=h-line_h-10:x=W-((W/tw)*325*n 350)" -acodec copy outVideo.mp4

Whoa, that's worthy of a command breakdown:
The drawtext video filter starts with an enable conditional [e.g. enable='gte(t,0)], while it has little affect in this example, this is a way to turn on the drawtext videofilter after a duration has expired.  This could prove valuable if you wish to postpone the drawing of text later into the video.
The fontfile is precisely that, the preferred font.  You may wish to play around with available fonts to select the most appropriate one for your overlay.
Font size, font color, borderwidth are all specifiers for the overlay font.
The next argument specifies the textfile that contains the overlay contents.  The format of the file is important, consisting of 1 continuous line containing the entirety of the lyrics.  Short pauses in lyrics can be done by adding spaces.
The reload command implies that the lyrics can change from frame to frame.  The last arguments specify the y-position of the beginning of the text.  Notice that the y-position video frame height (e.g. h), minus the height of the text along with an additional offset to draw the text up a bit from the absolute bottom of the video.  The x-position is the more interesting one, starting at the frame width (e.g. W) and frame-by-frame subtracting a dX.

The result:

It takes a good deal of patience and tweaking to get the timing right.

Have fun!

Friday, April 7, 2017

Hello Again -- I'm Back Baby!


Whelp, it's been quite some time since I authored a post.  Not to make excuses, but I kinda took it pretty tough when Danny Trejo, a long-time dedicated fan, unsubscribed from my blog posts.  Despite the fact that I painstakingly watched 'Machete', 'Machete Kills' and have pre-ordered tickets for 'Machete Kills in Space', Danny can't spare the time to read my itty-bitty blog.

Oh well, time goes on and I've gotten back on the old horse, you should see some new stuff coming your way next week.

Cheers.