小松鼠嚇了一跳,有了魔法眼鏡後,這世界看起來完全不一樣了

2011年5月21日 星期六

松鼠URL 2011-5-21

安全的幻影
Bruce Schneier: The security mirage


由於演化的關係,動物對於什麼是安全、什麼是危險有相當敏銳而正確的直覺。所以不需要理論、模型這一堆東西幫忙。人類其實也是....假如我們還生活在石器時代的話。其中一個和古時候的差別就是大眾傳播媒體。人類有一個很實用的經驗法則(或稱捷思)叫做可利用性法則(availability heuristic),簡單的說,就是如果你很熟、很快就能聯想起來的東西,應該就是比較重要的東西。比方說你常常聽說村子裡面有人被老虎吃掉,但是很少聽說有人被兔子吃掉,那老虎就比較危險一點。但是大眾媒體把一切都搞砸了。新聞顧名思義,就是報導罕見的事情。車禍天天發生、天天死人,沒什麼稀奇的,飛機比較少出問題,所以才會大幅報導。但是因為媒體從早報到晚,混淆了我們的可利用性法則,混淆了我們的直覺。
吃路邊或者速食可能比手機的電磁波危險的多。把 511 當成只是另外一天的人,遠比贊同王老師大地震說的人多,至少一開始是這樣的。但是媒體只會報導稀奇、不正常的事情。普通我們聽到王老師的講法,只會當成瘋子,根本不會去理會,但經過電視、報紙連續幾天的連環轟炸,混淆了我們的直覺,即使理智上你還是知道這完全是無稽之談,但你的「可利用性法則」會強迫你把這當成一件事情。

嬰兒的語言天才
Patricia Kuhl: The linguistic genius of babies


一歲前的嬰兒正在建立語言模型,重點是,對於嬰兒的語言學習,電視不但無法取代真人互動,而且是跟本完全沒有用。要有真人互動才拿打開嬰兒學習語言的開關。

笑容的隱藏能力
Ron Gutman: The hidden power of smiling


裡面提到,笑得越開懷的人,將來成就也會越高、壽命也會越長。乍看之下,似乎是個誤謬:因為健康較好、成就較高的人自然會笑得比較燦爛一點。
不過裡面用科學分析了笑容的反饋效應,告訴我們笑容會在腦中帶來快樂感,超過巧克力和金錢所能帶來的效應。
另外笑容也有感染力,能夠讓人心情平靜快樂。
之前結婚時,負責辦婚宴的小姐臉上總是掛著略帶誇張的笑容。可以說是有點「職業」,但我覺得是好的那種。因為大多數人結婚都是第一次,即使結婚很多次的人,也至少有一次是第一次。第一次做一件事時,有點緊張或者慌忙是自然的。穩定的笑容能夠有效的紓解不安。

如何綁鞋帶
Terry Moore: How to tie your shoes


五十歲的大叔終於發現自己(和多數人)以前鞋帶都沒有綁對。

Sean Carroll: Distant time and the hint of a multiverse

為什麼有時間這個東西?

2011年5月15日 星期日

Python: 下載 youtube 上的台灣電視節目

在坐月子中心,老婆想追一下之前連續劇的進度。月子中心裡的網路有限制,用 p2p 軟體不但佔用頻寬,而且不太可行的。雖然 cattail 在 android 上推出 台灣連續劇 app,但沒帶 hdmi 線,而且用我之前寫的 acer stream hdmi test,解析度不夠。雖說如此,既然影片已經在 youtube 上了,就有辦法看得到。
簡單看了一下,發現影片資料庫的網址。下載了 drama.db 後,用 sqlite database browser 檢視一下後,簡單寫個 python script 來生成 m3u8 檔。 現在的 VLC 已經能直接播放像是 http://youtube.com/watch?v=XXXXX 的 URL 。所以生成的 m3u8 也的卻能播放,不過由於網路速度太慢,播放斷斷續續的,無法盡如人意。所以乾脆寫個程式來下載 youtube 的影片。雖然 youtube-dl 很成熟,但用殺牛的大刀來切雞肉,有點太大材小用了,況且放入自己的程式碼中,還要花點時間讀程式碼。Youtube 的 HTML 碼改過不少,網路上一下也搜尋不到怎麼解析來源 flv 或者 mp4 的方式,所以乾脆就直接看 HTML source,配合上 regexp 來擷取影片 URL,也可以選擇自己想要的解析度。
雖然也可以配合 vlc 的 python binding 來播放,但是下載並且產生 m3u8 檔已經符合我的需求。
程式在 windows 7 下的 python 2.6 及 Ubuntu 的 python 2.7 測試過。在不同的機器下,除了一開始的幾個 path 外,也許檔名(drama_m3u8 和 fn)和 sys.argv[1]   的 encoding 也可能因為系統而不同也需要更改。
****
 2011-09-27補充
該資料庫已經不再繼續更新
*******

最後寫出的 python script 如下:

# -*- coding: utf8 -*-
import sqlite3
import re
import urllib
import sys
import time
import locale

DB_FILENAME=r'./drama.db'
OUT_DIR=ur'./'
PREF_FMTS=["35","34","5"] # youtube format: flv 480, flv 360, flv 240

def best_url(fmt_dict):
    k=filter(fmt_dict.has_key, PREF_FMTS)
    return fmt_dict[k[0]] if k else None

def try_to(f, n=1, message="do the work"):
    for i in range(n):
        try:
            return f()
        except:
            print "failed to %s (#%d)"%(message,i)
    return None

def get_fmts(v):
    url="http://youtube.com/watch?v=%s"%v
    read_url=lambda :urllib.urlopen(url).read()
    parse_fmt=lambda s: (s[0],urllib.unquote(s[1].decode('unicode_escape'))
                                     .replace(r'\/','/'))
    try:
        s=re.compile('"fmt_url_map": "([^"]*)"')\
            .search(try_to(read_url, 10, "read %s"%url))
        return dict(parse_fmt(x.split("|")) for x in s.group(1).split(","))
    except:
        print "failed to parse formats"
        return {}

def get_episodes(drama_name, ep_list=None, part_list=None):
    pbar=lambda p,k,t:"#"*int(p/2+0.5)+"."*(50-int(p/2+0.5))\
          +" %5.1f%% %6.1fKB/s %3d:%02d\r"%(p,k,t/60,t%60)
    def report():
        sec0=time.time()
        return lambda n, bs, size: sys.stdout.write(
                     pbar(min(n*bs*100.0/size,100.0),
                          n*bs/1024.0/max(1.0,time.time()-sec0),
                          int(time.time()-sec0)))
    conn=sqlite3.connect(DB_FILENAME)
    c=conn.cursor()
    query='''select pltitle, plvids from playlisttable
                                    where pltitle like ?
                                    order by plds'''
    c.execute(query, (u"%%%s%%"%drama_name,))
    enum_eps=((i+1,row) for i,row in enumerate(c) 
                        if not ep_list or i+1 in ep_list)
    for ep,row in enum_eps:
        print "[ep=%d]"%ep, row[0]
        drama_m3u8=OUT_DIR+ur'%s.m3u8'%row[0]
        vids=row[1].split(",")
        allparts=range(len(vids))
        vidnames=[row[0]+u" (%d).flv"%i for i in allparts]
        open(drama_m3u8,"w").write(u"\n".join(vidnames).encode("utf-8")+"\n")
        pl=set(allparts)&set(part_list) if part_list else allparts
        for part in pl:
            fn=OUT_DIR+vidnames[part]
            print fn
            url=best_url(get_fmts(vids[part]))
            if not url:
                continue
            if try_to(lambda :
              urllib.urlretrieve(url, fn, report()), 3, "get %s"%url):
                print "\nDone"
            else:
                print "\nFailed"
    conn.close()
    
if __name__ == "__main__":
    enc=locale.getpreferredencoding()
    try:
        drama_name=sys.argv[1].decode(enc) if len(sys.argv)>1 else u"犀利人妻"
        ep_list=map(int,sys.argv[2].split(",")) if len(sys.argv)>2 else None
        part_list=map(int,sys.argv[3].split(",")) if len(sys.argv)>3 else None
    except:
        print """Usage: tvshow_download showname [ep_list [part_list]]
Example: tvshow_download 犀利人妻 3,4,5  #download episode 3,4,5
         tvshow_download 犀利人妻        #donwload all episodes
         tvshow_download 犀利人妻 13 0,1 #download part 0,1 of episode 13
""".encode(enc)
    print "args:",drama_name, ep_list, part_list
    get_episodes(drama_name, ep_list, part_list)

2011年5月7日 星期六

Android 上的 midi

Android 2.2 上的 midi播放不太好聽,至少我的 acer stream 是如此。Android 系統採用 sonivox 的 EAS 來軟體合成 midi 音樂的,而且是使用 wavetable。但使用的wavetable格式不是比較常見的 SoundFont 而是 DLS。DLS 其實也是標準,而且 Windows 就內建有 gm.dls。 EAS預設的 wavetable 寫死在程式碼裡面,而且似乎就是 gm.dls。抓下 android 的 source 之後,就能編譯裡面的 eas_main.c 使用,來測試軟體合成的功能。
不過實際嘗試後發現無法使用,原因是 PlayFile 有點小 bug,要在
    file.fd = 0;
後面加上
    file.length=0;
    file.offset=0;
就行了。
接下來就是想嘗試改用比較好的 dls 檔,看看音色會不會改善一點點。雖然不期待改善太多,因為 android 中的 EAS 只能使用 22khz 的 sample rate。首先嘗試的是 windows 中的 gm.dls。可以用 EAS_LoadDLSCollection 順利載入,不過音色完全沒有改變。
想說換換其他的 DLS 檔看看,但是網路上不太容易找到 DLS 檔,找了很久只找到 dlsbyxg.dls, fury.dls, 還有兩種 ff8.dls。
很可惜,這幾個 dls 都無法在 EAS 中順利載入,分別會有不同的錯誤傳回碼。
沒有在詳細追錯誤的來源了,看來要改變計畫,直接編譯 fluidsynth 或 timidity++ 看看好了。如果能成功的話,再看看能不能做個 EAS 的介面讓 android 的 media player 直接取用?