GNU/Linux


ffmpeg: Create a video countdown – new post (2021) 2

The code below was used to generate the video countdown timers that are available in the following playlist using ffmpeg. These counters show seconds and fractions of seconds only. They do not bother with formating for minutes nor hours, etc.

#!/bin/bash

# This code will create a countdown video.
# If no command line arguments are provided, it will default to creating a 3-second video, with two fractional digits at 100 frames per second.
# It will print the elapsed and remaining times using two decimals accuracy.
defaultSeconds=3;
# If command line argument 1 is empty, the default value will be used.
seconds="${1:-$defaultSeconds}";

# Calculating how many digits are used to compose the seconds variable.
# We will use this information for zero-padding to avoid having the text move a lot.
# We used the shell parameter expansion to get the length of the variable value.
integerDigits="${#var}";

defaultFractionalDigits=2;
# If command line paremeter 2 is empty, the default value will be used.
fractionalDigits="${2:-$defaultFractionalDigits}";

#Computing how many frames per second are needed to maintain the accuracy of time based on the fractional digits.
fps=$((10 ** $fractionalDigits));

countDownFont=600;
countUpFont=100;
#Using a fixed width and fixed height font, to avoid having the text move around.
font='./Led.ttf';

#We are using the n variable: the frame number starting from 0 rather than the t variable, which is the timestamp expressed in seconds. We will get better accuracy on the decimals.
ffmpeg -loop 1 -i ~/Pictures/Black-Background.png -c:v libx264 -r $fps -t $seconds -vf "fps=$fps,
drawtext=fontfile=$font:fontcolor=yellow:fontsize=$countDownFont:x=(main_w-text_w)/2:y=(main_h-text_h)/2:text='%{eif\:($seconds-(n/$fps))\:d\:$integerDigits}.%{eif\:(mod($fps - mod(n, $fps), $fps))\:d\:$fractionalDigits}',
drawtext=fontfile=$font:fontcolor=yellow:fontsize=$countUpFont:x=(main_w-text_w)/2:y=((main_h-text_h)/2)+$countDownFont:text='Elapsed\: %{eif\:(n/$fps)\:d\:$integerDigits}.%{eif\:(mod(n, $fps))\:d\:$fractionalDigits}'" "$seconds seconds countdown timer with $fractionalDigits fractional digits accuracy.mp4";

Notes

  • We used a single black frame for the background that defined the video frame’s size as well.
  • Using the fps variable, we defined the number of Frames per Second for the video.
  • The seconds variable defined the number of seconds the duration of the video should be.
  • The fractionalDigits variable defines how many decimal digits should be shown after the dot.
  • countDownFont and countUpFont define the fonts’ size in the upper row and the lower one, respectively.
  • We used the drawtext directive twice to write to the frames.
  • font variable defines a fixed-width font to avoid having the text moving around.

Notes on the first drawtext

  • x=(main_w-text_w)/2 defines the X-coordinate of the location for the text on the frame, here we center the text horizontally on the frame.
  • (main_h-text_h)/2 defines the Y-coordinate of the location for the text on the frame, here we center the text vertically on the frame.
  • text='%{eif\:($seconds-(n/$fps))\:d\:$integerDigits}.%{eif\:(mod($fps - mod(n, $fps), $fps))\:d\:$fractionalDigits}' We print the remaining seconds for the video to finish with specific decimal digit accuracy.

Notes on the second drawtext

  • x=(main_w-text_w)/2 defines the X-coordinate of the location for the text on the frame, here we center the text horizontally on the frame.
  • y=((main_h-text_h)/2)+$countDownFont defines the Y-coordinate of the location for the text on the frame, here shift the text from the vertical center of the frame enough to move it under the main text.
  • text='Elapsed\: %{eif\:(n/$fps)\:d\:$integerDigits}.%{eif\:(mod(n, $fps))\:d\:$fractionalDigits}' We print the elapsed seconds since the video started with specific decimal digit accuracy.

Problem with compiling C# code on Ubuntu using the mono project while the source path contains Unicode characters

To avoid having the same issues as we did, avoid saving your code in folders that contain spaces and non-ASCII characters as it seems that the mono compiler on Ubuntu GNU/Linux is having some issues dealing with those.

We installed the mono compiler as follows:

sudo apt install mono-complete;

Then we tried to compile our C# code as follows:

mcs -out:program.exe Program.cs;

Which produced the following error:

error CS0016: Could not write to file `program'. Could not find a part of the path "윐뛶單/윐뛶單/program.exe".

By moving our code out of that folder, we were able to compile and execute our application as follows:

mono program.exe;


View Cisco Webex Recordings (or Join certain Live Sessions) on 64-bit Ubuntu 18.04 LTS

Recently, we were trying to view some Webex recordings on an updated Ubuntu 18.04LTS. After several attempts and various browsers (including the latest versions of Firefox, Google Chrome, Chromium), we could not view the recordings.

When clicking on the link, we would be redirected to install the Webex browser plugin, and then after we had installed it, we would either be redirected to a macOS installation file (Cisco_WebEx_Add-On.dmg) or to a Java servlet configuration file (CiscoWebExServlet).

We did lots of tests that are not worth mentioning, so we will go straight to the solution we followed from this page: https://gist.github.com/mshkrebtan/407786e334847544b40e7d6a8a53d247
What the solution recommended, was to install the 32-bit ESR version of Firefox, along with a 32-bit version of the Oracle JRE.

Enable support for 32-bit executables

Add the i386 architecture to the list of dpkg architectures :

sudo dpkg --add-architecture i386

Install the libraries required to execute ELF-32 executables:

sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386

Install Firefox 78.7.0esr ESR (32-bit)

Beginning with Firefox 52 (released March 2017), plug-in support is limited to Adobe Flash and drops support for NPAPI, impacting plugins for Java, Silverlight, and other similar NPAPI-based plugins. Hence you need the ESR release. You can read more on that here: https://www.java.com/en/download/help/firefox_java.xml
Download Firefox ESR for Linux (32-bit) from here.
Unpack it to somewhere, for example, to /opt/webex/:

sudo mkdir -p /opt/webex/
sudo tar -xjvf firefoxesr.tar.bz2 -C /opt/webex/

Install the libraries required for Firefox (i386) to run smoothly:

sudo apt-get install libgtk-3-0:i386 libasound2:i386 libdbus-glib-1-2:i386 libxt6:i386 libxtst6:i386 libcanberra-gtk-module:i386 libcanberra-gtk-3-module:i386 topmenu-gtk3:i386

Install 32-bit Oracle JRE

Download Oracle JRE for Linux (a tar.gz archive for x86 architecture) from here. Unpack it to /opt/webex/:

sudo tar -xzvf jrelinux-i586.tar.gz -C /opt/webex/
sudo mv /opt/webex/jre /opt/webex/jre

Enable Java support in Firefox

Create symbolic links for the Java browser plugin libraries:

sudo apt-get install libpangoxft-1.0-0:i386 libxft2:i386 libpangox-1.0-0:i386 libxmu6:i386 libxv1:i386 libasound2-plugins:i386;

Create a Firefox launch script

cat << 'EOF' | sudo tee /opt/webex/firefox.sh
!/bin/bash

export ENV_HOME=/opt/webex
export FIREFOX_HOME=$ENV_HOME/firefox
export MOZ_PLUGIN_PATH=$ENV_HOME/firefox/plugins
export JAVA_HOME=$ENV_HOME/jre
export PATH=$JAVA_HOME/bin:$PATH

$FIREFOX_HOME/firefox --no-remote -P
EOF

This script will start a new instance of Firefox with the ProfileManager. Choose an existing Firefox profile or create a new one.
You might want to specify a specific profile to start with. Just add the profile name after the -P flag.
Don’t forget to make the script executable:

sudo chmod a+x /opt/webex/firefox.sh

You might want to create a symlink, like this to make it easier to start the 32-bit version of Firefox using a custom name:

sudo ln -s /opt/webex/firefox.sh /usr/local/bin/firefox-i386

Start a Webex session

Launch the 32-bit Firefox using the script and join a Webex session.
If webex.com sends you a jnlp (or a CiscoWebExServlet) file, and Firefox asks what to do with it, download it.
Further, in the Firefox Preferences > Applications, set the action for JNLP files: they should be opened with javaws (Java Web Start) which can be found here:

/opt/webex/jre/bin/javaws

(Optional) Install the missing libraries required by Webex

Find out what required libraries are be missing (note that the session number may be different):

ldd ~/.webex/T30_MC/*.so | grep "not found"

You can use https://packages.ubuntu.com/ to find out which packages contain the libraries.


Installing TensorFlow 2 Object detection on Ubuntu 18.04 LTS 1

Following are some rough notes on Installing TensorFlow 2 Object detection on Ubuntu 18.04 LTS.
We were following this guide (https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/install.html) so we will be skipping some steps.

We had conda installed already from an older attempt so the following steps worked just fine.

conda create -n tensorflow pip python=3.8;
conda activate tensorflow;

We got an error with the following command so we used pip3 instead of pip.

pip install --ignore-installed --upgrade tensorflow==2.2.0;
Command 'pip' not found, but there are 18 similar ones.
pip3 install --ignore-installed --upgrade tensorflow==2.2.0;

Executing the above gave us another error:

Collecting tensorflow==2.2.0
Could not find a version that satisfies the requirement tensorflow==2.2.0 (from versions: 0.12.1, 1.0.0, 1.0.1, 1.1.0rc0, 1.1.0rc1, 1.1.0rc2, 1.1.0, 1.2.0rc0, 1.2.0rc1, 1.2.0rc2, 1.2.0, 1.2.1, 1.3.0rc0, 1.3.0rc1, 1.3.0rc2, 1.3.0, 1.4.0rc0, 1.4.0rc1, 1.4.0, 1.4.1, 1.5.0rc0, 1.5.0rc1, 1.5.0, 1.5.1, 1.6.0rc0, 1.6.0rc1, 1.6.0, 1.7.0rc0, 1.7.0rc1, 1.7.0, 1.7.1, 1.8.0rc0, 1.8.0rc1, 1.8.0, 1.9.0rc0, 1.9.0rc1, 1.9.0rc2, 1.9.0, 1.10.0rc0, 1.10.0rc1, 1.10.0, 1.10.1, 1.11.0rc0, 1.11.0rc1, 1.11.0rc2, 1.11.0, 1.12.0rc0, 1.12.0rc1, 1.12.0rc2, 1.12.0, 1.12.2, 1.12.3, 1.13.0rc0, 1.13.0rc1, 1.13.0rc2, 1.13.1, 1.13.2, 1.14.0rc0, 1.14.0rc1, 1.14.0, 2.0.0a0, 2.0.0b0, 2.0.0b1)
No matching distribution found for tensorflow==2.2.0

To fix it we upgraded pip using the following command.

python3 -m pip install --upgrade pip;

Then we tried again, which installed most packets but gave a new error:

pip3 install --ignore-installed --upgrade tensorflow==2.2.0;
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
launchpadlib 1.10.6 requires testresources, which is not installed.
Successfully installed absl-py-0.11.0 astunparse-1.6.3 cachetools-4.2.1 certifi-2020.12.5 chardet-4.0.0 gast-0.3.3 google-auth-1.27.0 google-auth-oauthlib-0.4.2 google-pasta-0.2.0 grpcio-1.35.0 h5py-2.10.0 idna-2.10 importlib-metadata-3.4.0 keras-preprocessing-1.1.2 markdown-3.3.3 numpy-1.19.5 oauthlib-3.1.0 opt-einsum-3.3.0 protobuf-3.14.0 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.25.1 requests-oauthlib-1.3.0 rsa-4.7.1 scipy-1.4.1 setuptools-53.0.0 six-1.15.0 tensorboard-2.2.2 tensorboard-plugin-wit-1.8.0 tensorflow-2.2.0 tensorflow-estimator-2.2.0 termcolor-1.1.0 typing-extensions-3.7.4.3 urllib3-1.26.3 werkzeug-1.0.1 wheel-0.36.2 wrapt-1.12.1 zipp-3.4.0

To fix this error we used:

sudo apt install python3-testresources;

Then tried again the pip installation with success.

pip3 install --ignore-installed --upgrade tensorflow==2.2.0;
Successfully installed absl-py-0.11.0 astunparse-1.6.3 cachetools-4.2.1 certifi-2020.12.5 chardet-4.0.0 gast-0.3.3 google-auth-1.27.0 google-auth-oauthlib-0.4.2 google-pasta-0.2.0 grpcio-1.35.0 h5py-2.10.0 idna-2.10 importlib-metadata-3.4.0 keras-preprocessing-1.1.2 markdown-3.3.3 numpy-1.19.5 oauthlib-3.1.0 opt-einsum-3.3.0 protobuf-3.14.0 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.25.1 requests-oauthlib-1.3.0 rsa-4.7.1 scipy-1.4.1 setuptools-53.0.0 six-1.15.0 tensorboard-2.2.2 tensorboard-plugin-wit-1.8.0 tensorflow-2.2.0 tensorflow-estimator-2.2.0 termcolor-1.1.0 typing-extensions-3.7.4.3 urllib3-1.26.3 werkzeug-1.0.1 wheel-0.36.2 wrapt-1.12.1 zipp-3.4.0

We then executed the following to test the installation:

python3 -c "import tensorflow as tf;print(tf.reduce_sum(tf.random.normal([1000, 1000])))";

Then we proceeded to get the TensorFlow models:

mkdir ~/TensorFlow;
cd ~/TensorFlow;
git clone https://github.com/tensorflow/models;

We then downloaded protobufs and extracted them to our home directory.
To test the installation we did the following.

export PATH="/home/bob/protoc-3.14.0-linux-x86_64:$PATH";
cd /home/bob/TensorFlow/models/research;
protoc object_detection/protos/*.proto --python_out=.;

Then we proceeded to the COCO installation:

pip3 install cython;

The above will solve the problem of:

gcc: error: pycocotools/_mask.c: No such file or directory
cd ~;
git clone https://github.com/cocodataset/cocoapi.git;
cd cocoapi/PythonAPI;
make;
cp -r pycocotools ~/TensorFlow/models/research/;

Finally we proceeded to Install the Object Detection API.

cd ~/TensorFlow/models/research/;
cp object_detection/packages/tf2/setup.py .;
python3 -m pip install .;

To test the installation we executed the following:

python3 object_detection/builders/model_builder_tf2_test.py;

We then downloaded the samples and executed the camera sample with success!!

To check against a video instead of a camera, we changed the following line from:

cap = cv2.VideoCapture(0)

to

cap = cv2.VideoCapture('/home/bob/Desktop/a2/A01_20210210164306.mp4')