10.30.2012

Funtoo Linux and Intel Rapid Start Technology

Recently I got myself a new laptop of NEC's Lavie Z (LZ550/H). It's really a nice laptop, weights only 875g in its 13.3" size. NEC said it is the world's most lightweight 13.3" laptop ever been.

The laptop encompasses an Intel 7 series chipset UM77 which supports Intel Rapid Start, a technology let the laptop goes into the deeper ACPI S4 (hibernate) from ACPI S3 (standby) after some periods of time.

It differs from that the hibernation is directly supported in the hardware, so that you will not see any traditional boot sequences during waking up from a hibernated machine as before, just a flash. It seems Apple implements Safe Sleep by the use of it in their Macs.

The laptop runs linux (Funtoo Linux) and I found out no instructions about how to setup Intel Rapid Start up with linux. But it ends up being not too complicated:
  • an SSD
  • an BIOS supports Intel Rapid Start Technology
  • a partition equal or greater than the laptop's physical memory
I use gdisk to create an extra 4GB partition since the laptop is 4GB model, and then you must give the partition a specified id as to be recognized by the hardware. According to Intel and Gigabyte's manuals, it must be:
  • in diskpart, id: 84, or
  • in gdisk, guid: D3BFE2DE-3DAF-11DF-BA40-E3A556D89593


After that you can reboot the machine into BIOS and check whether the Intel Rapid Start Technology options is on. If you see something like "No valid IFFS partition found" then there must be something wrong in the previous partitioning step.


Now you can see in the BIOS there are additional options can be configured the Rapid Start. Since Intel releases no software for Linux currently, you can only configure it via BIOS.

To test if it works, configure it to "Entry Imemediately", and make your latop go into S3 standby:

# echo -n mem > /sys/power/state
  1. it goes into standby.
  2. it wake up immediately after standby.
  3. then it will flush memory contents into the partition.
  4. goes into hibernation.
  5. you can only wake it up by pressing the power button.
  6. after powering up again, you are now at where you were as if it had never powered down.

I've just set it up for hours, don't know whether it is stable yet, but it did work. I'm at vanilla-sources-3.6.3 with CK patches.

There are some times that it goes into hibernation immediately while I setup up a 5 mins period, and there are some times that it wake up from first S3 but not going to hibernation anymore..., since I just got my Funtoo prototype without any further settings for ACPI/laptop, I cannot make sure it's my problem or not.

8.16.2012

Build A Live Audio Streaming System

這是一個手工打造串流音樂台的記錄,source 是以 ffmpeg 擷取 foobar2000 的音源,轉檔並傳送到 server 那邊的 ffserver,
  • source: Intel Core 2 Duo E6850, 8GB ram, Windows 7 64bit.
  • server: Intel Atom D510, 4GB ram, FreeBSD 9.0 amd64.
Server 端只負責對外的服務,不需要特別強悍的效能。
這個串流系統總共用到這些東西,
  • ffmpeg:@source,擷取音源
  • foobar2000:@source,播音樂,並且將現在播放的資訊丟到遠方的節目表 service
  • ffserver :@server,接收 ffmpeg 來源,並提供對外的 streaming
  • socket.io:@server,接收 foobar2000 現在播放的資訊,推播到網頁上
  • nginx :@web,網頁介面
  • jPlayer:@web,HTML5 audio library

ffmpeg & ffserver


  • ogg in webm, 192kb for Firefox, Chrome.
  • mp3, 256kb for Chrome, Internet Explorer, Safari.

<stream mu.webm="mu.webm">
Feed mu.ffm
Format webm
AudioCodec libvorbis
AVOptionAudio flags +global_header
AudioBitRate 192
AudioChannels 2
AudioSampleRate 44100
NoVideo
</stream>

<stream mu.mp3="mu.mp3">
Feed mu.ffm
Format mp3
AudioCodec libmp3lame
AVOptionAudio flags +global_header
AudioBitRate 256
AudioChannels 2
AudioSampleRate 44100
NoVideo
</stream>

只要這邊設定好了,就已經能用常用的 player 打開 URL 聽串流。

foobar2000


因為是採用 ffmpeg 直接擷取整台電腦的音源,沒辦法直接將 foobar2000 的 meta informations 串流在一起,meta informations 必須另外自己處理,所以 foobar2000 這邊除了播音樂,還要負責將現在播放的資訊丟到遠方的節目表服務,這邊是以 foobar SDK 弄了一個 
它能將現在播放的資訊以 HTTP POST 傳到設定頁中指定的 URL,傳送的動作會在「歌曲變更」時觸發。

socket.io


socket.io 是 node 上非常方便的 Web Socket implementation,對於支援的的 browser,會直接以 WebSocket 溝通,否則會降回到傳統的幾個 long-pulling 機制。這邊以 node 與 socket.io 弄出一個節目表的服務,它的功用在

nginx


一者是想讓對外的服務介面一致,一者是 node 不花心思寫的話,serving static files 效能不彰。這裡實際上我讓 foobar2000 的 HTTP POST 與 browser client 的推播導向跑在 localhost 的節目表 service。

    server {
        server_name mu.adios.tw;

        location / {
            root        /home/www/adios.tw/mu;
            index       mu.html;
            try_files   $uri $uri/ @home;
        }
        location ~ /\.git {
            deny        all;
        }
        location ~ ^/foo {
            proxy_pass  http://127.0.0.1:2000;
        }
        location ~ ^/muuun {
            proxy_http_version  1.1;
            proxy_pass          http://127.0.0.1:2000;
        }
        location @home {
            proxy_pass  http://127.0.0.1;
        }
    }

網頁介面


網頁介面包括使用了現成的 jPlayer & CirclePlayer,與修改後的版本
這邊使用到的技術有 HTML5 Audio, Socket.io, CSS 3 WebFont

整個系統之後可以朝向多人 hosters 的目標發展,也就是由聽眾決定,要不要繼續聽目前的曲子,還是要直接跳至 foobar2000 清單中的下一首。這個過程能經過投票決定。這部份會是 foobar2000 與 socket.io 的相關設計。



8.15.2012

在 Windows 用 ffmpeg 錄桌面

比較新版本的 ffmpeg 支援 dshow input,在 Windows 下能直接使用 DirectShow 相容的裝置 (webcam, mic) 當輸入源,

ffmpeg -f dshow -list_devices true -i dummy

會列出所有它能認出的 dshow devices。接著安裝虛擬的 dshow 裝置,視需求安裝,
如果要擷取整台電腦的音源(想錄一般麥克風、或是列出的名稱是亂碼的音源裝置),第二項是必須要裝的。注意要用這兩個 virtual device 需要 32bit 的 ffmpeg

ffmpeg -rtbufsize 512000k -f dshow -i video=screen-capture-recorder:audio=virtual-audio-capturer
       -vcodec libx264 -preset fast -tune stillimage -x264opts crf=26
       -acodec libvorbis -aq 3
        screencast.mkv

這樣會將現在看到的桌面與任何動作以 x264 壓縮到 screencast.mkv 這個影片中,就算是在被遠端桌面的狀況下,也能正常錄製;當下桌面的解析度就會是影片壓製的解析度。

最近版本這樣壓出來的影片會是 4:4:4 的,若要丟到 Youtube 上,必須是 yuv420p,所以要指定,

ffmpeg -rtbufsize 512000k -f dshow -i video=screen-capture-recorder:audio=virtual-audio-capturer
       -vcodec libx264 -preset fast -tune stillimage -x264opts crf=26
       -acodec libvorbis -aq 3
       -pix_fmt yuv420p
       -sws_flags lanczos
       -vf crop=1440:810:0:0,scale=1280:720
        screencast.mkv

假設你的螢幕解析度是 1440x900,為了上傳 youtube 方便,想弄成 720p 的 16:9,可以先 crop 成 16:9 的 1440x810,然後再 scale 成 1280x720,如上的綠字部份。像是這個測試就是從 1024x640 crop and scale to 1280x720。

如果要流暢一點,還能指定 input 的 framerate (defaults to 25fps),詳細請看 ffmpeg 的 man pages。

記得,如果是在 mac 下…



可以直接用 QuickTime Player 錄桌面!

8.14.2012

試試 CSS3 Web Font

如果只是想要好看的英文字型,Google Web Font 提供非常方便的服務:
  • 能選擇多組字型
  • 能預覽這些字型在不同樣式、位置的搭配效果
  • 字型是公開授權過的
  • 不用擔心 @font-face 的多平台多字型問題
可惜沒有提供中文、日文字型,畢竟這些字型的檔案都太大(2MB+)。

TO HOST FONT


把字型檔案擺在正確的位置,並多加一行 @font-face 在 CSS 前面,就能讓 font-family 使用自已放在 server 上的字體:

<style type="text/css">
        @font-face {
                font-family: 'mikachan';
                src: url('/fonts/mikachan.otf');
        }
        /* some elsewhere ... */
        body {
                font-family: 'mikachan', sans-serif;
        }
</style>

在最簡單的情況下,用 Chrome 與 Firefox 能正常下載和顯示這字型。若字型要讓
  • 老版本的 Internet Explorer 使用 (eot)
  • 其它平台的瀏覽器使用 (svg, ttf)
  • 讓它遵循規範
那麼 @font-face 這邊就必須加上多種格式:

<style type="text/css">
        @font-face {
                font-family: 'mikachan';
                src:    url('/fonts/mikachan.eot');
                src:    url('/fonts/mikachan.eot?#iefix') format('embedded-opentype'),
                        url('/fonts/mikachan.woff') format('woff'),
                        url('/fonts/mikachan.ttf') format('truetype'),
                        url('/fonts/mikachan.svg#mikachan') format('svg');
                font-weight: normal;
                font-style: normal;
        }
</style>

當中的數個 src properties 是必要的,Nice Web Type 這邊記錄和說明每一行必須存在的原因,也詳列數年來各種不同的 bullet-proof 技巧。

不同字型格式的轉換可以用 www/ttf2eot 和 www/sfnt2woff,或是直接用線上的轉換服務:
它們會同時幫你產生對應的 @font-face CSS 和 demo page。

如果要 host 的字型變多了,可以寫一個產生 CSS @font-face 的 handler:

<?php
header('Content-Type: text/css');

function fill($buffer) {
        global $font_family;
        global $file_name;
        return str_replace('{FILE_NAME}', $file_name, str_replace('{FONT_FAMILY}', $font_family, $buffer));
}
?>

<?php ob_start('fill'); ?>
@font-face {
    font-family: '{FONT_FAMILY}';
    src: url('/fonts/{FILE_NAME}.eot');
    src: url('/fonts/{FILE_NAME}.eot?#iefix') format('embedded-opentype'),
         local('☺'),
         url('/fonts/{FILE_NAME}.woff') format('woff'),
         url('/fonts/{FILE_NAME}.ttf') format('truetype'),
         url('/fonts/{FILE_NAME}.svg#{FILE_NAME}') format('svg');
    font-weight: normal;
    font-style: normal;
}
<?php ob_end_flush(); ?>

甚至判斷瀏覽器 User Agent,僅回應指定的 @font-face rule,這樣就不需特別作 IE bullet proof。

NGINX CONFIGURATION


新增或修改這幾種附檔名的 MIME Type:

types {
    application/x-font-ttf                ttf;
    application/x-font-woff               woff;
    application/vnd.ms-fontobject         eot;
}

以及 nginx.conf,

server {
    ...
    location /fonts {
        add_header  Access-Control-Allow-Origin http://mu.adios.tw;
        gzip_types  image/svg+xml application/x-font-ttf application/vnd.ms-fontobject;
    }
    ...
}

傳輸用 gzip 是讓我們的字體能小一點點(woff 是已經壓過的格式,所以不再 gzip),要注意的是那個 header,W3C 規範瀏覽器必須禮貌性遵守字型的同源政策,也就是:

  • 你在瀏覽 Host A 的網頁
  • Host A 的 @font-face src properties 指到 Host B
  • 瀏覽器向 Host B 問字型時,Host B 會先回應含有這條 header 的訊息
  • 瀏覽器將這條 header 比對 Host A,如果一樣,才會下載並使用字型

IE9: CS3111: Unknown Error


如果 Internet Explorer 9 無法顯示字型,打開開發者工具,檢查看看是不是吐這條訊息,這表示字型檔案錯誤。詳細原因我也不明暸,應該是字體內有些屬性 Windows 不懂,這發生在從 otf 轉換的 eot 字型,後來我是拿為原本設計給 windows 的 ttf 格式來轉換 eot,就正常無虞了。

顯示字型的一致性


在字型正在被下載的過程中,採用該字體的文字:
  • Chrome 不顯示任何東西,直到字體下載完,才會顯示
  • Firefox 顯示預設字型,直到字體下載完,才會更新
WebFont Loader 能彌平這種不一致性。要嘛就讓所有瀏覽器都不顯示,要嘛就是先顯示預設字型。

7.13.2012

HTML5 Live Audio Streaming with ffserver

Recently I've successfully set up an HTML5 live audio streaming by using ffmpeg and ffserver. It streams well on most HTML5 browsers including latest IE9, Firefox and Chrome. The streaming source comes from an PC running Windows, and the streaming server runs on FreeBSD.

At streaming source, to make all your sounds (i.e. what you can hear) capable of being captured by ffmpeg, you need to create an virtual device which is DirectShow-compatible so that the latest ffmpeg can recognize it as an audio capturer.
There should exist an virtual-audio-capturer entry after checking with the command,

ffmpeg -f dshow -list_devices true -i dummy

and the following is the command to stream what you hear out to the remote server.

ffmpeg -f dshow -i audio=virtual-audio-capturer http://server:8090/feed.ffm

At server side, we need to configure two kinds of audio streams in order to provide HTML5 audio compatibilities among mainstream browsers,
  • set up an mp3 stream with libmp3lame audio codec. (IE, Safari, Chrome)
  • set up an webm stream with libvorbis audio codec. (Firefox, Opera, Chrome)
Adding one more line to both of the streams you just set up,

AVOptionAudio flags +global_header

to make them live streaming capable.

You can directly open the streaming in VLC(webm, mp3) or foobar2000(mp3) to test whether it works or not. And note that there are still some issues between ffmpeg and ffserver while streaming.

The MP3 Stream Cannot be Played on Internet Explorer 9


After googling, I just know that IE9 accepts only server response of audio/mpeg as mime-type to mp3 stream, whereas ffserver(N-42472-gd3abbb1) responds the old audio/x-mpeg one.

Here is the dirty one-line fix to the issue,

diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index 8a9f788..14ec70c 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -499,7 +499,7 @@ static int mp3_write_trailer(AVFormatContext *s)
 AVOutputFormat ff_mp3_muxer = {
     .name              = "mp3",
     .long_name         = NULL_IF_CONFIG_SMALL("MPEG audio layer 3"),
-    .mime_type         = "audio/x-mpeg",
+    .mime_type         = "audio/mpeg",
     .extensions        = "mp3",
     .priv_data_size    = sizeof(MP3Context),
     .audio_codec       = CODEC_ID_MP3,

then ffserver feeds IE9 happily.

OGG Stream Format Plays Abnormal on Most Players


When specifying the libvorbis stream with OGG format, audio stream being played on Firefox or Opera will come off and on. The problem exists by directly opening it using VLC or foobar2000. Hence I think it maybe an unknown bug comes with ffserver's OGG format.

For the same libvorbis stream, I changed it to using WEBM format, and everything is OK. So I recommend to choose webm as your encapsulation format for libvorbis streams.

Libvorbis Transcoding Fails in a Ranged Bitrate


For the libvorbis codecs, I encountered a strange behavior of transcoding failed at source ffmpeg(N-42347-g299387e). It failed at bitrate 128kb, 160kb and any value lower than 192kb.

I haven't find out how to fix it yet, so just setting bitrate to 192kb at the moment to prevent the failure transcoding.

Realtime Buffer X% Full


if you see this at source point occasionally while streaming stop,

[dshow @ 01f1c000] real-time buffer 1412% full! frame dropped!

You may increase buffer size by adding rtbufsize option to prevent this error,

ffmpeg -rtbufsize 512000k -f dshow ...