2015年4月27日 星期一

透過 Script 合併 MPEG2-TS (Transport Stream / TS) 與 ffmpeg 轉檔

因緣際會,處理一些用 M3U 串起來的一堆瑣碎的 .ts 檔案,這些檔案透過 M3U 的格式,可清楚描述第幾秒要播放哪個片段。然而,在一些測試上會略顯麻煩 Orz 所以撰寫一些 script 跟 ffmpeg 來把這些東西在整合成單一檔案 :P

眾多 ts 檔案該怎樣合併成一則?其實單純用 file append 即可:

$ cat 1.ts 2.ts 3.ts > output.ts

所以,假設有一個 M3U 時,可以透過以下指令抓出:

$ grep -v "#" list.m3u | xargs
1.ts 2.ts 3.ts ...


可惜啊,資料比數太 command line 可能會出爆,建議改用 script 來處理,例如 PHP:

<?php
foreach(explode("\n", file_get_contents($m3u_input)) as $line) {
if (empty($line) || $line[0] == '#')
continue;
$raw = file_get_contents($file);
if (!empty($raw))
file_put_contents("$output.raw", $raw, FILE_APPEND);
}


如此一來,就可以把一票 .ts 檔重新建立成單一檔案 .raw 。接著,再用 ffmpeg 轉成想要測試的格式吧!關於 ts 轉 mp4 ,可以透過 ffmepg 處理,其中 ffmpeg 會自己判斷輸出的格式(此例是 mp4),所以有需要也可以用 output.avi:

$ ffmpeg -i input.ts -vcodec copy -acodec copy output.mp4
$ ffmpeg -i input.ts -vcodec copy -acodec copy -bsf:a aac_adtstoasc output.mp4


如果有一票目錄 + M3U 的話,就掃一下目錄建立一票相關的,接著可以用 find 再把這一票轉一轉:

$ find . -name "*.raw" -exec  ffmpeg -i {} -vcodec copy -acodec copy -bsf:a aac_adtstoasc {}.mp4 \;

2015年4月25日 星期六

PHP CodeIgniter - 使用 Memcached

官方文件寫得很簡單,簡單的無法看懂:

@ https://ellislab.com/codeigniter/user-guide/libraries/caching.html
$this->load->driver('cache');
$this->cache->memcached->save('foo', 'bar', 10);


後來我自己去 trace 原始碼才知道該怎樣設定跟測試。首先,新增一個設定檔:

$ vim application/config/memcached.php
$config['memcached'] = array(
        'hostname' => 'Your_memecached_cluster',
        'port' => 11211,
        'weight' => 1
);


接著,使用:

class My_Library {
public function __construct() {
$this->ci =& get_instance();
$this->init();
}
public function init() {
$this->ci->load->driver('cache');
return $this->ci->cache->is_supported('memcached');
}
public function set($key, $value, $tts) {
return $this->ci->cache->memcached->save($key, $value, $tts);
}
public function delete($key) {
$this->ci->cache->memcached->delete($key);
}
}


關鍵之處就是要呼叫 $this->ci->cache->is_supported('memcached') 這段,才會從 application/config/memcached.php 把資訊更新進來 Orz

若需要 debug 的話:

$ find . -name "*mem*"
./system/libraries/Cache/drivers/Cache_memcached.php


找到 $this->_memcached 可以善用它,例如 $this->_memcached->getResultCode();

2015年4月21日 星期二

iOS 開發筆記 - 製作 iOS Simulator app 版本送交給 Facebook 進行 review (creating-ios-simulator-build-for-review)

似乎...Facebook SDK 文件沒找到?只好隨意 Google 一些資料

$ cd /path/project
$ xcodebuild -showsdks
OS X SDKs:
OS X 10.9                     -sdk macosx10.9
OS X 10.10                     -sdk macosx10.10

iOS SDKs:
iOS 8.3                       -sdk iphoneos8.3

iOS Simulator SDKs:
Simulator - iOS 8.3           -sdk iphonesimulator8.3

$ xcodebuild -arch i386 -sdk iphonesimulator8.3


若用 CocoaPods (碰到 ld: library not found for -lPods-XXX ) 或 xcworkspace 維護的,需要多一點指令:

$ xcodebuild -arch i386 -sdk iphonesimulator8.3 -workspace YourName.xcworkspace -scheme YourName

接著,想執行看看:

$ ios-sim launch /Users/user/Library/Developer/Xcode/DerivedData/YourName-xxxxxx/Build/Products/Debug-iphonesimulator/YourName.app

其中 ios-sim 可以逛一下這邊:https://github.com/phonegap/ios-sim

2015年4月16日 星期四

PHP 逆向工程 - 列出已定的 function 及相關參數

最近接手一包程式碼,發現這個 php source code 裡頭的 function 定義搞了很多層:

<?php
if (!function_exists('a')) {
function a($input) {
$input = base64_decode($input);
// ...decoding
$raw = file_get_contents(__FILE__);
// comparing...
}
}
eval(a("XXXXX"));


因為是這樣的模式,猜測應該是有保護程式碼不能在其他地方用。為了想知道做了什麼事,就惡搞一下,試試能不能看到到底有哪些 function 被定義或是使用:

<?php
require '/path/enc_src.php';

print_r(get_defined_functions()['user']);
foreach(get_defined_functions()['user'] as $func) {
        $rf = new ReflectionFunction($func);
        echo "func name: [$func]\n";
        foreach( $rf->getParameters() as $param )
                print "$param\n";
}


如此一來,就可以發他定義了哪些 function 及參數意義等:

func name: [func_name_1]
Parameter #0 [ <required> $a ]
Parameter #1 [ <required> $b ]
Parameter #2 [ <required> $c ]
Parameter #3 [ <required> $d ]
Parameter #4 [ <required> $e ]
...

接下來有空再追開了什麼檔案...

2015年4月15日 星期三

AWS 筆記 - 使用 Amazon ElastiCache - Memcached Cluster



由於服務是儲存在 RDBMS ,以此做出許多關聯設計。有朋友分享實際案例,對於線上服務盡量不要用 JOIN 等技術,例如把查詢結果定期儲存一張表上來使用,然而,在開發階段只能一切求快 XD 因此,快速開發後就想一下有沒有快一點的強化服務方式,於是乎就想到透過 memcache 來暫存儲存結果。於是乎,來使用一下 Amazon ElastiCache。

原先想自己在 EC2 上架設,接著就想到要維護 Cluster 的問題,所以就...先試一下別人的產品吧 XD 開幾台最便宜的 cache.t2.micro (555MB memory),然後開個兩台。

接著就可以得到一個入口點,如:

your_name.cfg.your_region.cache.amazonaws.com:11211

因此,有人幫你維護 cluster 也是件好事吧!有專人維護入口點,也有人維護節點,都可以在 AWS 控制界面看到。



以 PHP 程式範例就接用吧!

<?php

$memcache = new Memcache;
$memcache->connect('your_name.cfg.your_region.cache.amazonaws.com', 11211);

for ($i=0 ; $i<1024 * 1024 * 30 ; ++$i) {
        $key = "key-$i";
        $memcache->set($key, $i);
}


執行:

$ time php test.php

就可以在 Amzon ElastiCache 管理介面觀看那兩個 node 的情況,簡言之,兩個 node 是一直彼此 sync 的啦。且過程中也可以很便利的透過 Add Node 新增機器,而程式碼由於都寫定在一個入口點了,所以維護非常輕鬆。




若是把範例程式改成這樣,會發現跑一陣子後(約四千,大概跟 DNS Cache有關)會出現連不到的問題,我想,站在 cache 機制上,服務本身也不會出錯才對 :P

<?php
for ($i=0 ; $i<1024 * 1024 * 30 ; ++$i) {
        $key = "key-$i";

        $memcache = new Memcache;
        $memcache->connect('your_cache.cfg.region.cache.amazonaws.com', 11211);
        $memcache->set($key, $i);
        $memcache->get($key);
        $memcache->close();
        echo "finish $i\n";
}


$ php test.php
...

PHP Warning:  Memcache::connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /path/test.php on line 6
PHP Stack trace:
PHP   1. {main}() /path/test.php:0
PHP   2. Memcache->connect() /path/test.php:6
PHP Notice:  Memcache::connect(): Server your_cache.cfg.region.cache.amazonaws.com (tcp 11211, udp 0) failed with: php_network_getaddresses: ge
taddrinfo failed: Name or service not known (0) in /path/test.php on line 6
PHP Stack trace:
PHP   1. {main}() /path/test.php:0
PHP   2. Memcache->connect() /path/test.php:6
PHP Warning:  Memcache::connect(): Can't connect to your_cache.cfg.region.cache.amazonaws.com:11211, php_network_getaddresses: getaddrinfo fail
ed: Name or service not known (0) in /path/test.php on line 6
PHP Stack trace:
PHP   1. {main}() /path/test.php:0
PHP   2. Memcache->connect() /path/test.php:6