Tuesday, April 30, 2019

Streaming Custom Videos in Google Hangouts


With this method, I was able to send Google Hangouts any video contents, such as me with a news broadcast background, while the small TV in that background is showing my desktop playing a live Youtube video.

OBS is a fine tool that enables us to overlay various visual/audio sources, on the fly, for streaming and/or recording. Unfortunately, it doesn't support a virtual cam under Linux (there is a plugin that only works under Windows), i.e. I can't send a complex composition of a live desktop screen, webcam, video, etc. to Google Hangouts.

Webcamoid is another fine tool that supports output to a virtual cam under Linux, which Google Hangouts can directly use.

Several attempts were made, but I wasn't able to get a result with low enough latency for video conferencing. The video latency caused an unacceptable out-of-sync problem with the audio.

I reached an easy workaround, which is resource heavy, but works quite well.
  1. Use OBS to construct the target scene, say, a chroma keyed webcam, with a video background, and a logo foreground, as well as a live chat overlay.
  2. In OBS, right click on the preview, and project it under a separate screen.
  3. In Webcamoid, choose that screen as the source.
  4. In Google Hangouts, choose Webcamoid's virtual cam instead of the real webcam.
  5. Voila! Now I have full control of what others see in my video conferencing.
This solution needs one whole screen just to link OBS and webcamoid. Any of the following improvement of either project will make this workflow even better:
Hopefully either will come soon.

Friday, October 13, 2017

uwsgi wrong python interpreter

In some projects, I use uwsgi behind nginx to drive Django. I also use virtualenv to manage my environments (by the way, Panda's introducing .ix and then deprecating it wasn't fun). In a recent update, I was pulling my hair out trying to figure out why I'm getting the following error message, and a wrong Python interpreter.

Could not find platform independent libraries
Could not find platform dependent libraries
Consider setting $PYTHONHOME to [:]
Python version: 3.5.4 |Continuum Analytics, Inc.| (default, Aug 14 2017, 13:26:58)  [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
Set PythonHome to /opt/anaconda
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named 'encodings'

It turned out that the problem was in the binary code of uwsgi in my environment. It was compiled for another environment, with the environment path hard-coded in. Yes, in the binary. I had done that in another environment and the compiled package stayed in the pip cache, and the new environment just picked it up from the cache, causing inconsistency!

The solution:

pip install --no-cache uwsgi

Tuesday, July 11, 2017

Ergodox EZ Configurator Layer Manipulation

Ergodox EZ provides a great configurator; however, it doesn't provide all editing functions I need. Unfortunately, the source code disappeared from github (multiple unofficial documents have links to that repo so I assume the source was once available; this is rather disappointing, since the company made it look like that they are using all open source resources.)

One of the functions that I need the most is swapping the layers.

Here's what I did to achieve it:

Upon examining the minimized javascript, it was written against the React framework. Therefore, I installed the React debugger extension for chrome, in order to find and manipulate the variable that stores the layer information.

Once the extension is installed, reload the page, and open up the Developer Tools in Chrome.
Click on React to open the debugging panel.
Make sure the correct scope "App" is selected.
Now the variable $r will contain the React object, including the state, for editing.
The layers (including all key assignment) information is in the array: $r.state.layout.layers

Here's an example of swapping layer 3 and 4.

$r.state.layout.layers = [

Note that if there are layer switching keys, you'll also need to manually modify those from the GUI.

I also did some batch editing offline, and then re-assign the whole $r.state.layout.layers
by first converting the variable to JSON and write it to a local file, with this snippet.

Also when you copy/create a layer, make sure to use the GUI to first allocate the variable $r.state.layout.layers[x].keyboard_layout_id on their server and then carefully copy those values.

Here's my current setup, if you are interested.

Saturday, February 6, 2016

Fixing Lenovo U31-70 WiFi Problem


Lenovo U31-70 is a lightweight laptop. Its WiFi performance has been a headache to many people. Most people report unstable signal dropping.

For those who use Windows and are experiencing unstable WiFi problem, you just need to solve the hardware problem.

I use Linux, so I had to go a different route to solve my driver problem.

The Hardware Problem

I opened up the laptop, and found that the two antenna cables were not properly attached to the card. There was a tape (not shown in the picture) trying to keep the two cables attached, but failed due to the tension from the bending; also, the screw to attach the card onto the main board is too close to one of the antenna contacts so it automatically grounds it, making that antenna useless. This is a design problem.

I first re-attached the two cables back to their contacts and re-tape them, and put some non-conductive material between the screw and the contact to prevent the grounding. It helped.

The Atheros 10K Driver Problem under Linux

I had used several Thinkpads since its IBM days, so I was quite surprised to have found that this Lenovo's Atheros 10K chip was not supported under Linux. People were reporting stable driver performance under Windows, and some efforts were made to bring the firmware from Windows driver to Linux. I waited a few months for Linux kernel to come to version 4.3 and spent a lot of time trying various hacks to get the driver working. I was never able to get stable performance.

I decided to replace the card with Intel Dual Band Wireless AC 3160, which is well supported by native Linux.

(I have no idea which antenna cable is intended for WiFi and which is for bluetooth, but this works for me; besides, tension-wise, this is the only way I could keep the contacts isolated.)

It has been working flawlessly.

Saturday, January 30, 2016

Coordinate Transformation Matrix for Touchscreen in multi-screen setup in X11

Currently I have a twin screen setup in Arch Linux, like this:

On the left, DELL 1901FP is turned 90 degree counter-clockwise in its portrait mode. On the right, DELL P2314T, a touch screen, is in its regular landscape orientation, with its bottom line aligning with the bottom of the rotated screen on the left.

Here's my xorg.conf for that. (Although one can also setup screen arrangement in KDE/Plasma/Gnome/etc., for KDM/SDDM/GDM/etc. to recognize it in the login screen, it's important to put this in xorg.conf)

X11 sees a (1024+1920) wide * 1280 high DISPLAY, with an upper-right corner being invisible.

Since the touchscreen is just a regular pointer device (through its driver), when I put my finger on the left border of the touchscreen on the right, the cursor goes all the way to the very left of the DISPLAY. Touchscreen is only useful if the cursor follows my finger. Therefore, we need to do some Input Coordinate Transformation.

Coordinate Transformation Matrix is precisely the needed configuration.

From the documentation above, our goal is to map the following coordinates on the left (X11's default behavior) to the ones on the right:

So that means we are solving the following system:

Here's the solution:

Convert it to float numbers:

Now we can put these numbers into the configuration, as the document instructed.

However, it doesn't work. The cursor stays on the lower right. After some debugging, I found the offsets 1024 and 200 were the culprit. They need to be a percentage, i.e. relative to the full width and height.

So 1024.0/(1024+1929) = .3476766, 200.0/1280 = .15625

I put it in /usr/share/sddm/scripts/Xsetup (or /usr/share/config/kdm/Xsetup if you haven't upgraded to plasma) as well as ~/.xprofile so it automatically runs every time.

Edit 2016-02-22: I ended up having 3 screens with two in the portrait orientation. SDDM correctly uses metamodes setting in xorg.conf, regardless of the screen power. However, KDE is more sensitive to that so sometimes the layout is messed up. Here's a script to quickly correct that.

Monday, October 19, 2015

Install Sibelius 8.0.1 on a non-C drive in Windows

Since Sibelius 8.0.0, Avid changed the installer, and it has a serious bug -- it assumes you have a C: drive before letting you choose the installation destination. I figured out a hack to install it. However, it doesn't work for Sibelius 8.0.1, so here's another way to approach it, before Avid's Sibelius team fixes the bug.

I don't have a C: drive, but Sibelius insists that I must do, so what we are trying to do here is to temporarily create a C: drive, and then create a link pointing crucial directories back to my system drive, K:. After Sibelius is successfully installed, we can then safely remove the temporary C: drive.

First, we need to create a Virtual Hard Drive (VHD) as our C:\ drive. I learned how to do this via this answer:
  • Start → run → diskmgmt.msc (accept all defaults... I'm not doing anything special below) 
  • From the menu bar select Action → Create VHD 
  • Choose the location and name the file (which will be the vhd) and specify the size and click OK. My file is K:\virtual_drive_c.vhd and the size is 1G, but I made it dynamic so it's actual size is around 16MB. 
  • Right click on the Disk # (underneath will be Unknown and the size and "Not Initialized"). Select "Initialize Disk" and click OK 
  • Right click on the black bar of the unallocated disk space and select "new simple volume". A wizard opens up an on the second page it lets you assign the drive letter. We want C: here. Complete the wizard and you're done!
Now that we have a C: drive, we can link the important folders. I learned how to do that from this post:
  • Start → run → cmd, then right click and choose "Run as Administrator". 
  • In the prompt, type the following:
K:\>mklink /j "C:\Program Files" "K:\Program Files"
Junction created for C:\Program Files <<===>> K:\Program Files

K:\>mklink /j "C:\Program Files (x86)" "K:\Program Files (x86)"
Junction created for C:\Program Files (x86) <<===>> K:\Program Files (x86)

After that, Sibelius installation should run normally. In the installer, I still choose to install the program to K:, to avoid future problems running Sibelius, since the bug is on the installer, not Sibelius itself.

Afterwards, you can reboot, and safely delete the vhd file.

Thursday, September 24, 2015





我小學正是Apple II電腦剛進入台灣的時候。那時候Apple II能插一張「佳佳漢卡」來顯示中文。打字方面只有倉頡與注音。我試學了幾次倉頡,最後都放棄。主要也因為那時候打中文的機會少,所以茍且用注音好多年。


















由於上述的版權問題,軟體無法直接包含大易,所以這個過程只能手動。雖然花點力氣,也能把大易都裝上去(gcin, Lime, Open vanilla, 內建, JB/iAccess),但辛苦的是,每次系統或是作業環境升級,這個過程就得重來一次。







順道一提,這陣子我開始用手機上 Google 的中文語音輸入,準確度很高,但輸入標點符號很麻煩,而且跨平台很不方便,隱私上也有些顧慮。