2012-09-30 22:24

[轉載][PHP] preg_replace 效能測試 (將兩個空白字元以上取代成一個)

轉載自:[PHP] preg_replace 效能測試 (將兩個空白字元以上取代成一個) 小惡魔 – 電腦技術 – 工作筆記 – AppleBOY

preg_replace 可以使用正規語法來取代字串任何字元,,今天探討取代空白字元的效能,雖然這是個不起眼的效能評估,一般人不太會這樣去改,不過這是國外 PHP Framework 有人提出來修正的,經過許多人的測試一致同意。功能就是一篇文章內如果有多餘的空白能空取代成一個,一般人都會用 \s+ 正規語法,畢竟大家都知道 \s 代表單一空白或 \r 等符號,但是國外有人提出用 {2,} 方式來取代空白。程式碼如下,大家可以測試看看。

<?php
$nb = 10000;
$str = str_repeat('Hi, I am appleboy  ' . "\n", 10);
$t1 = microtime(true);
for ($i = $nb; $i--; ) {
    preg_replace('/\s+/', ' ', $str);
}
$t2 = microtime(true);
for ($i = $nb; $i--; ) {
    preg_replace('/ {2,}/', ' ', 
        str_replace(array("\r","\n","\t","\x0B","\x0C"),' ',$str)
    );
}
$t3 = microtime(true);

echo $t2 - $t1;
echo "\n";
echo $t3 - $t2;

測試結果(1萬次)

PHP 5.3.3
old: 0.13053798675537
new: 0.058536052703857

PHP 5.3.15
old: 0.11732506752014
new: 0.071418046951294

PHP 5.3.17
old: 0.11612010002136
new: 0.07065486907959

PHP 5.4.5
old: 0.1185781955719
new: 0.066012859344482

PHP 5.4.7
old: 0.11343121528625
new: 0.066931962966919

結論至少快蠻多的,如果整體資料量再大一點,我想差別會更大,那至於要不要用呢,就看個人了 XD。
2012-09-05 13:32

Apache 消失的 ServerLimit 參數

在某些版本的 Apache 中如果單純加大 MaxClients 的設定值,就會得到以下的錯誤訊息:
WARNING: MaxClients of 300 exceeds ServerLimit value of 256 servers,
  lowering MaxClients to 256. To increase, please see the ServerLimit
  directive.

這時必須再增加 ServerLimit 這個設定,而這個設定在設定檔中並沒有提示,所以需要額外加入。
<IfModule mpm_prefork_module>
    ServerLimit         500 # 額外加入
    StartServers         10
    MinSpareServers      10
    MaxSpareServers      20
    MaxClients          300
    MaxRequestsPerChild   0
</IfModule>

停止並啟動(單純 restart 無法套用設定)
service apache2 stop
service apache2 start

參考來源:
Gilbert.tw > Apache 之謎樣 ServerLimit 指令 (directive)
2012-09-05 13:01

[Ubuntu] 用 logrotate 定期切割 Apache log 檔

Ubuntu 預設已經為 Apache 建立了 log 分割管理,但在建立虛擬主機(Virtual Host),但又很龜毛的將 log 獨立到個別的子目錄下的話,預設的 logrotate 是沒有辦法處理到的,所以請記得為這龜毛的動作加上額外設定。

編輯屬於 Apache 的設定檔,在檔案最後面加上額外的設定。
vim /etc/logrotate.d/apache2
/var/log/apache2/blog/*.log {
    daily
    missingok
    rotate 52
    dateext
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        /etc/init.d/apache2 reload > /dev/null
    endscript
}

參數說明:
daily 每天整理,其他還有 weekly, monthly, yearly
missingok 允許 log 檔不存在
nomissingok 不允許 log 檔不存在,會丟出錯誤 (預設)
rotate 7 保留 7 次的分割
size 1M 大小超過 1M 就執行分割,單位可以是 1024, 100k, 4M, 1G
dateext 用日期來建立分割檔名,而非流水號
dateformat -%Y%m%d 日期格式
compress 壓縮分割,預設用 gzip (預設)
nocompress 不壓縮分割
delaycompress 延後壓縮直到下一次 rotate
notifempty 如果 log 是空的就不執行
copytruncate 以[複製清空]的方式分割 log,這樣可以用不到 postrotate 設定
mail xxx@address 將分割內容用 mail 寄出
prerotate/endscript 分割前要執行的指令
postrotate/endscript 分割後要執行的指令


測試設定檔是否正確
logrotate -f /etc/logrotate.conf


參考來源:
使用 logrotate 定期整理 Rails Log 檔案
[ubuntu] 使用 logrotate 定期切割壓縮 apache2 的 log 檔
2012-09-05 11:46

[轉載] [MySQL] QueryCache原理

轉載自:PHP 程式 學習 筆記本 [Mysql]QueryCache原理

原理
QueryCache(下面簡稱QC)是根據SQL語句來cache的。一個SQL查詢如果以select開頭,那麼MySQL服務器將嘗試對其使用QC。每個Cache都是以SQL文本作為key來存的。在應用QC之前,SQL文本不會被作任何處理。也就是說,兩個SQL語句,只要相差哪怕是一個字符(例如大小寫不一樣;多一個空格等),那麼這兩個SQL將使用不同的一個CACHE。

不過SQL文本有可能會被客戶端做一些處理。例如在官方的命令行客戶端裡,在發送SQL給服務器之前,會做如下處理:
  • 過濾所有註釋
  • 去掉SQL文本前後的空格,TAB等字符。注意,是文本前面和後面的。中間的不會被去掉。


下面的三條SQL裡,因為SELECT大小寫的關係,最後一條和其他兩條在QC裡肯定是用的不一樣的存儲位置。而第一條和第二條,區別在於後者有個註釋,在不同客戶端,會有不一樣的結果。所以,保險起見,請儘量不要使用動態的註釋。在PHP的mysql擴展裡,SQL的註釋是不會被去掉的。也就是三條SQL會被存儲在三個不同的緩存裡,雖然它們的結果都是一樣的
SELECT * FROM people where name='surfchen';
SELECT * FROM people where /*hey~*/name='surfchen';
SELECT * FROM people where name='surfchen';


目前只有select語句會被cache,其他類似show,use的語句則不會被cache。

因為QC是如此前端,如此簡單的一個緩存系統,所以如果一個表被更新,那麼和這個表相關的SQL的所有QC都會被失效。假設一個聯合查詢裡涉及到了表A和表B,如果表A或者表B的其中一個被更新(update或者delete),這個查詢的QC將會失效。

也就是說,如果一個表被頻繁更新,那麼就要考慮清楚究竟是否應該對相關的一些SQL進行QC了。一個被頻繁更新的表如果被應用了QC,可能會加重數據庫的負擔,而不是減輕負擔。我一般的做法是默認打開QC,而對一些涉及頻繁更新的表的SQL語句加上SQL_NO_CACHE關鍵詞來對其禁用CACHE。這樣可以儘可能避免不必要的內存操作,儘可能保持內存的連續性。

那些查詢很分散的SQL語句,也不應該使用QC。例如用來查詢用戶和密碼的語句——「select pass from user where name='surfchen'」。這樣的語句,在一個系統裡,很有可能只在一個用戶登陸的時候被使用。每個用戶的登陸所用到的查詢,都是不一樣的SQL文本,QC在這裡就幾乎不起作用了,因為緩存的數據幾乎是不會被用到的,它們只會在內存裡佔地方。


存儲塊
在本節裡「存儲塊」和「block」是同一個意思
QC緩存一個查詢結果的時候,一般情況下不是一次性地分配足夠多的內存來緩存結果的。而是在查詢結果獲得的過程中,逐塊存儲。當一個存儲塊被填滿之後,一個新的存儲塊將會被創建,並分配內存(allocate)。單個存儲塊的內存分配大小通過query_cache_min_res_unit參數控制,默認為4KB。最後一個存儲塊,如果不能被全部利用,那麼沒使用的內存將會被釋放。如果被緩存的結果很大,那麼會可能會導致分配內存操作太頻繁,系統系能也隨之下降;而如果被緩存的結果都很小,那麼可能會導致內存碎片過多,這些碎片如果太小,就很有可能不能再被分配使用。

除了查詢結果需要存儲塊之外,每個SQL文本也需要一個存儲塊,而涉及到的表也需要一個存儲塊(表的存儲塊是所有線程共享的,每個表只需要一個存儲塊)。存儲塊總數量=查詢結果數量*2+涉及的數據庫表數量。也就是說,第一個緩存生成的時候,至少需要三個存儲塊:表信息存儲塊,SQL文本存儲塊,查詢結果存儲塊。而第二個查詢如果用的是同一個表,那麼最少只需要兩個存儲塊:SQL文本存儲塊,查詢結果存儲塊。

通過觀察Qcache_queries_in_cacheQcache_total_blocks可以知道平均每個緩存結果占用的存儲塊。它們的比例如果接近1:2,則說明當前的query_cache_min_res_unit參數已經足夠大了。如果Qcache_total_blocks比Qcache_queries_in_cache多很多,則需要增加query_cache_min_res_unit的大小。

Qcache_queries_in_cache * query_cache_min_res_unit(sql文本和表信息所在的block佔用的內存很小,可以忽略)如果遠遠大於query_cache_size-Qcache_free_memory,那麼可以嘗試減小query_cache_min_res_unit的值。


調整大小
如果Qcache_lowmem_prunes增長迅速,意味著很多緩存因為內存不夠而被釋放,而不是因為相關表被更新。嘗試加大query_cache_size,儘量使Qcache_lowmem_prunes零增長。


啟動參數
show variables like 'query_cache%' 可以看到這些信息。
query_cache_limit:如果單個查詢結果大於這個值,則不Cache
query_cache_size:分配給QC的內存。如果設為0,則相當于禁用QC。要注意QC必須使用大約40KB來存儲它的結構,如果設定小於40KB,則相當于禁用QC。QC存儲的最小單位是1024 byte,所以如果你設定了一個不是1024的倍數的值,這個值會被四捨五入到最接近當前值的等於1024的倍數的值。
query_cache_type:
0 完全禁止QC,不受SQL語句控制(另外可能要注意的是,即使這裡禁用,上面一個參數所設定的內存大小還是會被分配);
1啟用QC,可以在SQL語句使用SQL_NO_CACHE禁用
2可以在SQL語句使用SQL_CACHE啟用。

query_cache_min_res_unit:每次給QC結果分配內存的大小


狀態
show status like 'Qcache%' 可以看到這些信息。
Qcache_free_blocks:當一個表被更新之後,和它相關的cache blocks將被free。但是這個block依然可能存在隊列中,除非是在隊列的尾部。這些blocks將會被統計到這個值來。可以用FLUSH QUERY CACHE語句來清空free blocks。

其他幾個狀態變量的意義:
Qcache_free_memory 表示查詢緩存區現在還有多少的可用內存,如果很小,考慮增加query_cache_size
Qcache_hits 表示查詢緩存區的命中個數,也就是直接從查詢緩存區作出響應處理的查詢個數
Qcache_inserts 表示查詢緩存區此前總過緩存過多少條查詢命令的結果
Qcache_lowmem_prunes 表示查詢緩存區已滿而從其中溢出和刪除的查詢結果的個數
Qcache_not_cached 自mysql進程啟動起,沒有被cache的只讀查詢數量(包括select,show,use,desc等)
Qcache_queries_in_cache 當前被cache的SQL數量
Qcache_total_blocks:在QC中的blocks數。一個query可能被多個blocks存儲,而這幾個blocks中的最後一個,未用滿的內存將會被釋放掉。例如一個QC結果要佔6KB內存,如果query_cache_min_res_unit是4KB,則最後將會生成3個blocks,第一個block用來存儲sql語句文本,這個不會被統計到query+cache_size裡,第二個block為4KB,第三個block為2KB(先allocate4KB,然後釋放多餘的2KB)。每個表,當第一個和它有關的SQL查詢被CACHE的時候,會使用一個block來存儲表信息。也就是說,block會被用在三處地方:表信息,SQL文本,查詢結果。

優化提示:如果Qcache_lowmem_prunes 值比較大,表示查詢緩存區大小設置太小,需要增大。如果Qcache_free_blocks 較多,表示內存碎片較多,需要清理,flush query cache

根據我看的 《High Performance MySQL》中所述,關於query_cache_min_res_unit大小的調優,書中給出了一個計算公式,可以供調優設置參考:
query_cache_min_res_unit = (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache

還要注意一點的是,FLUSH QUERY CACHE 命令可以用來整理查詢緩存區的碎片,改善內存使用狀況,但不會清理查詢緩存區的內容,這個要和RESET QUERY CACHE相區別,不要混淆,後者才是清除查詢緩存區中
的所有的內容。
2012-06-04 01:29

[轉載] 自適應網頁設計

轉載自:自适应网页设计(Responsive Web Design) 阮一峰

随着 3G 的普及,越来越多的人使用手机上网。

移动设备正超过桌面设备,成为访问互联网的最常见终端。于是,网页设计师不得不面对一个难题:如何才能在不同大小的设备上呈现同样的网页?



手机的屏幕比较小,宽度通常在 600 像素以下,PC 的屏幕宽度,一般都在 1000 像素以上(目前主流宽度是1366×768),有的还达到了 2000 像素。同样的内容,要在大小迥异的屏幕上,都呈现出满意的效果,并不是一件容易的事。

很多网站的解决方法,是为不同的设备提供不同的网页,比如专门提供一个 mobile 版本,或者 iPhone / iPad 版本。这样做固然保证了效果,但是比较麻烦,同时要维护好几个版本,而且如果一个网站有多个 portal(入口),会大大增加架构设计的复杂度。

于是,很早就有人设想,能不能"一次设计,普遍适用",让同一张网页自动适应不同大小的屏幕,根据屏幕宽度,自动调整布局(layout)?




一、"自适应网页设计"的概念

2010 年,Ethan Marcotte 提出了"自适应网页设计"(Responsive Web Design)这个名词,指可以自动识别屏幕宽度、并做出相应调整的网页设计。

他制作了一个范例,里面是《福尔摩斯历险记》六个主人公的头像。如果屏幕宽度大于 1300 像素,则 6 张图片并排在一行。



如果屏幕宽度在 600 像素到 1300 像素之间,则 6 张图片分成两行。



如果屏幕宽度在 400 像素到 600 像素之间,则导航栏移到网页头部。



如果屏幕宽度在 400 像素以下,则 6 张图片分成三行。



mediaqueri.es 上面有更多这样的例子。

这里还有一个测试小工具,可以在一张网页上,同时显示不同分辨率屏幕的测试效果,我推荐安装。


二、允许网页宽度自动调整

"自适应网页设计"到底是怎么做到的?其实并不难。

首先,在网页代码的头部,加入一行 viewport元标签

<meta name="viewport" content="width=device-width, initial-scale=1" />

viewport 是网页默认的宽度和高度,上面这行代码的意思是,网页宽度默认等于屏幕宽度(width=device-width),原始缩放比例(initial-scale=1)为 1.0,即网页初始大小占屏幕面积的 100%。

所有主流浏览器都支持这个设置,包括 IE9。对于那些老式浏览器(主要是 IE6、7、8),需要使用 css3-mediaqueries.js

<!--[if lt IE 9]>
    <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script>
<![endif]-->


三、不使用绝对宽度

由于网页会根据屏幕宽度调整布局,所以不能使用绝对宽度的布局,也不能使用具有绝对宽度的元素。这一条非常重要。

具体说,CSS代码不能指定像素宽度:

width: xxx px;

只能指定百分比宽度:

width: xx%;

或者

width: auto;


四、相对大小的字体

字体也不能使用绝对大小(px),而只能使用相对大小(em)。

body {
    font: normal 100% Helvetica, Arial, sans-serif;
}

上面的代码指定,字体大小是页面默认大小的 100%,即 16 像素。

h1 {
    font-size: 1.5em; 
}

然后,h1 的大小是默认大小的 1.5 倍,即 24 像素(24/16=1.5)。

small {
    font-size: 0.875em;
}

small 元素的大小是默认大小的 0.875 倍,即 14 像素(14/16=0.875)。


五、流动布局(fluid grid)

"流动布局"的含义是,各个区块的位置都是浮动的,不是固定不变的。

.main {
    float: right;
    width: 70%; 
}

.leftBar {
    float: left;
    width: 25%;
}

float 的好处是,如果宽度太小,放不下两个元素,后面的元素会自动滚动到前面元素的下方,不会在水平方向 overflow(溢出),避免了水平滚动条的出现。

另外,绝对定位(position: absolute)的使用,也要非常小心。


六、选择加载CSS

"自适应网页设计"的核心,就是 CSS3 引入的 Media Query 模块。

它的意思就是,自动探测屏幕宽度,然后加载相应的 CSS 文件。

<link rel="stylesheet" type="text/css" media="screen and (max-device-width: 400px)" href="tinyScreen.css" />

上面的代码意思是,如果屏幕宽度小于 400 像素(max-device-width: 400px),就加载 tinyScreen.css 文件。

<link rel="stylesheet" type="text/css" media="screen and (min-width: 400px) and (max-device-width: 600px)" href="smallScreen.css" />

如果屏幕宽度在 400 像素到 600 像素之间,则加载 smallScreen.css 文件。

除了用 html 标签加载 CSS 文件,还可以在现有 CSS 文件中加载。

@import url("tinyScreen.css") screen and (max-device-width: 400px);


七、CSS 的 @media 规则

同一个 CSS 文件中,也可以根据不同的屏幕分辨率,选择应用不同的 CSS 规则。

@media screen and (max-device-width: 400px) {
    .column {
        float: none;
        width: auto;
    }
    #sidebar {
        display: none;
    }
}

上面的代码意思是,如果屏幕宽度小于 400 像素,则 column 块取消浮动(float:none)、宽度自动调节(width:auto),sidebar 块不显示(display:none)。


八、图片的自适应(fluid image)

除了布局和文本,"自适应网页设计"还必须实现图片的自动缩放

这只要一行 CSS 代码:

img { max-width: 100%; }

这行代码对于大多数嵌入网页的视频也有效,所以可以写成:

img, object { max-width: 100%; }

老版本的 IE 不支持 max-width,所以只好写成:

img { width: 100%; }

此外,windows 平台缩放图片时,可能出现图像失真现象。这时,可以尝试使用 IE 的专有命令:

img { -ms-interpolation-mode: bicubic; }

或者,Ethan Marcotte 的 imgSizer.js

addLoadEvent(function() {
    var imgs = document.getElementById("content").getElementsByTagName("img");
    imgSizer.collate(imgs);
});

不过,有条件的话,最好还是根据不同大小的屏幕,加载不同分辨率的图片。有很多方法可以做到这一条,服务器端和客户端都可以实现。

(完)
2012-05-05 01:53

[轉載] 让PHP更快的提供文件下载

作者:Laruence
本文地址:http://www.laruence.com/2012/05/02/2613.html

一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件.

但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作. 于是, 很多时候, 我们采用让PHP来做转发, 为用户提供文件下载.

<?php
    $file = "/tmp/dummy.tar.gz";
    header("Content-type: application/octet-stream");
    header('Content-Disposition: attachment; filename="' 
        . basename($file) . '"');
    header("Content-Length: ". filesize($file));
    readfile($file);

但是这个有一个问题, 就是如果文件是中文名的话, 有的用户可能下载后的文件名是乱码.

于是, 我们做一下修改(参考: :

<?php
    $file = "/tmp/中文名.tar.gz";
 
    $filename = basename($file);
 
    header("Content-type: application/octet-stream");
 
    //处理中文文件名
    $ua = $_SERVER["HTTP_USER_AGENT"];
    $encoded_filename = urlencode($filename);
    $encoded_filename = str_replace("+", "%20", $encoded_filename);
    if (preg_match("/MSIE/", $ua)) {
        header('Content-Disposition: attachment; filename="'
            . $encoded_filename . '"');
    } else if (preg_match("/Firefox/", $ua)) {
        header("Content-Disposition: attachment; filename*=\"utf8''"
            . $filename . '"');
    } else {
        header('Content-Disposition: attachment; filename="'
            . $filename . '"');
    }
 
    header('Content-Disposition: attachment; filename="'
        . $filename . '"');
    header("Content-Length: ". filesize($file));
    readfile($file);

恩, 现在看起来好多了, 不过还有一个问题, 那就是readfile, 虽然PHP的readfile尝试实现的尽量高效, 不占用PHP本身的内存, 但是实际上它还是需要采用MMAP(如果支持), 或者是一个固定的buffer去循环读取文件, 直接输出.

输出的时候, 如果是Apache + PHP mod, 那么还需要发送到Apache的输出缓冲区. 最后才发送给用户. 而对于Nginx + fpm如果他们分开部署的话, 那还会带来额外的网络IO.

那么, 能不能不经过PHP这层, 直接让Webserver直接把文件发送给用户呢?

今天, 我看到了一个有意思的文章: How I PHP: X-SendFile.

我们可以使用Apache的module mod_xsendfile, 让Apache直接发送这个文件给用户:

<?php
    $file = "/tmp/中文名.tar.gz";
 
    $filename = basename($file);
 
    header("Content-type: application/octet-stream");
 
    //处理中文文件名
    $ua = $_SERVER["HTTP_USER_AGENT"];
    $encoded_filename = urlencode($filename);
    $encoded_filename = str_replace("+", "%20", $encoded_filename);
    if (preg_match("/MSIE/", $ua)) {
        header('Content-Disposition: attachment; filename="'
            . $encoded_filename . '"');
    } else if (preg_match("/Firefox/", $ua)) {
        header("Content-Disposition: attachment; filename*=\"utf8''"
            . $filename . '"');
    } else {
        header('Content-Disposition: attachment; filename="'
            . $filename . '"');
    }
 
    header('Content-Disposition: attachment; filename="'
            . basename($file) . '"');
 
    //让Xsendfile发送文件
    header("X-Sendfile: $file");

X-Sendfile头将被Apache处理, 并且把响应的文件直接发送给Client.

Lighttpd和Nginx也有类似的模块, 大家有兴趣的可以去找找看


mod-xsendfile 在 Ubuntu 的安裝方法:
sudo apt-get install libapache2-mod-xsendfile
2012-05-05 01:27

[PHP] 使用 php5-ffmpeg 擷取影片圖片

前幾天在玩 FFmpeg 的時後,突然發現 Ubuntu 上多了 php5-ffmpeg 這個擴充套件,就想來玩玩看,看好不好用,有兩個結論:
  1. 讀取影片取決於 FFmpeg 的支援性,如果想要什麼格式都支援的話,建議自己重新編譯 FFmpeg。
  2. 效率並沒有我想像中的快,兩分鐘的影片取十張圖,大約 30 秒。
安裝方法:
sudo apt-get install ffmpeg php5-ffmpeg php5-gd

擷圖測試範例:
<?php
$page = 10;
$prefix = 'screencap';

$mov = new ffmpeg_movie('gt.avi');
$count = $mov->getFrameCount();
$range = (int)round($count/($page+1));

for($i=1; $i<=$page; $i++){
    $frameNum = $range*$i;
    $imgFile = $prefix.'_'.$i.'.png';

    $frame = $mov->getFrame($frameNum);
    if(!$frame){ continue; }

    $gdImage = $frame->toGDImage();
    if(!$gdImage){ continue; }

    imagepng($gdImage, $imgFile);
    imagedestroy($gdImage);

    echo '<img src="'.$imgFile.'" border="1" /><br />';
}

參考文件:
ffmpeg_movie object methods
FFmpeg and PHP
2012-05-03 14:49

[Ubuntu 11] HTTP Live Streaming 安裝與測試

安裝 Apache
apt-get install apache2

/etc/apache2/mods-available/mime.conf 加入以下內容:
# HLS file type
AddType application/x-mpegURL .m3u8
AddType video/MP2T .ts


Ubuntu 11.04 預設的 FFmpeg 是沒有啟用 h.264 的支援,所以要自己編譯。

安裝編譯時所需要的套件
apt-get update
apt-get install build-essential checkinstall subversion git libfaac-dev libjack-jackd2-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libsdl1.2-dev libtheora-dev libva-dev libvdpau-dev libvorbis-dev libx11-dev libxfixes-dev libxvidcore-dev texi2html yasm zlib1g-dev libx264-dev librtmp-dev


編譯 FFmpeg
cd /opt
git clone git://git.videolan.org/ffmpeg
cd ffmpeg

./configure --prefix=/usr --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --disable-ffplay --enable-shared --enable-gpl --enable-postproc --enable-version3 --enable-nonfree --enable-avfilter --enable-pthreads --enable-vdpau --enable-librtmp 

make -j$(grep processor /proc/cpuinfo |wc -l)

checkinstall --pkgname=ffmpeg --pkgversion="5.0.1" --backup=no --deldoc=yes --default


segmenter 是用來切割 FFmpeg 轉好的 ts 檔
編譯 segmenter
cd /opt
svn co http://httpsegmenter.googlecode.com/svn/trunk
cd trunk

sed 's/\/local//g' Makefile.txt > Makefile

make -j$(grep processor /proc/cpuinfo |wc -l)
checkinstall --pkgname=segmenter --pkgversion="2" --backup=no --deldoc=yes --default



測試影片轉檔
cd /var/www
ffmpeg -i gt4.avi -f mpegts -vcodec libx264 -acodec libmp3lame gt4_pre.ts

ffmpeg -i gt4.avi -f mpegts -acodec libmp3lame -ar 48000 -ab 64k -s 720x480 -vcodec libx264 -b 800k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 200k -maxrate 800k -bufsize 800k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 720:480 -g 30 -async 2 gt4_pre.ts


測試 RTMP 串接轉檔
ffmpeg -i rtmp://flashstream.adobe.com/ondemand/flash/cs5/prod/production-performance_400x224 -f mpegts -vcodec libx264 -acodec libmp3lame rtmp_pre.ts


測試影片切割
segmenter -i gt4_pre.ts -d 10 -o gt4_pre -x stream.m3u8 -p http://192.168.0.10/


利用 pipe 從轉檔到切割
ffmpeg -i gt4.avi -f mpegts -vcodec libx264 -acodec libmp3lame - |segmenter -i - -d 10 -o gt4_pre -x stream.m3u8 -p http://192.168.0.10/


m3u8 檔案格式
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXTINF:11,
http://192.168.0.10/gt4_pre-1.ts
#EXTINF:11,
http://192.168.0.10/gt4_pre-2.ts
#EXTINF:11,
http://192.168.0.10/gt4_pre-3.ts
#EXTINF:11,
http://192.168.0.10/gt4_pre-4.ts
#EXTINF:5,
http://192.168.0.10/gt4_pre-5.ts
#EXT-X-ENDLIST


以 HTML5 播放影片
<html>
  <head><title>Video Test</title></head>
  <body>
    <center>
      <video tabindex="0" width="720" height="480"><source src="/stream.m3u8"></video>
    </center>
  </body>
</html>


參考文件:
How to compile and install ffmpeg in Ubuntu 11.04
Install FFmpeg and x264 on Ubuntu Lucid Lynx 10.04 LTS
iPhone HTTP Streaming with FFMpeg and an Open Source Segmenter
HTTP Live Streaming draft-pantos-http-live-streaming-08
http live streaming(m3u8 streaming)(m3u8)