1. Define the Problem and App Solution
2. Define Personas
3. Find the Use Case and User Story
4. Find the feature list
5. Prioritize the feature list (user story? scrum? kaban?)
6. MVP
7. Define main work flows and others.
8. Prototype High Level Wireframe
9. Confirm the wireframe and prototype with users
10. Coding and Testing
references:
https://www.udacity.com/course/ux-design-for-mobile-developers--ud849
星期一, 12月 26, 2016
星期三, 11月 30, 2016
FFMPEG 降低frame數,但保留audio及高視訊品質
ffmpeg -y -i Chap01_06.mp4 -r 15 -c:v libx264 -crf 18 -strict -2 -movflags faststart -c:a copy nnChap01_06.mp4
星期六, 11月 05, 2016
Scrum and user story好投影片
http://www.slideshare.net/ertjona/workshop-paper-prototying-game
User Story Mapping Workshop (Design Skills 2016)
http://www.slideshare.net/mozyrko/user-story-mapping-design-skills-2016?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=5
Agile meetuphsinchu user story mapping workshop
http://www.slideshare.net/ssusere62027/agile-meetuphsinchu-user-story-mapping-workshop?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=23
Agile meetup - user story mapping workshop
http://www.slideshare.net/ssusere62027/agile-meetup-userstorymapping?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=8
User Story Mapping Workshop
http://www.slideshare.net/danapylayeva/user-story-mapping-workshop?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=15
comments:
product goals? ->personas-> user story mapping -> scrum sprint
Agile and user story workshop
http://www.slideshare.net/petersaddington/agile-and-user-story-workshop-peter-saddington?qid=754f9138-698f-4676-b8ee-7d546510d079&v=&b=&from_search=7
User Story Mapping Workshop (Design Skills 2016)
http://www.slideshare.net/mozyrko/user-story-mapping-design-skills-2016?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=5
Agile meetuphsinchu user story mapping workshop
http://www.slideshare.net/ssusere62027/agile-meetuphsinchu-user-story-mapping-workshop?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=23
Agile meetup - user story mapping workshop
http://www.slideshare.net/ssusere62027/agile-meetup-userstorymapping?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=8
User Story Mapping Workshop
http://www.slideshare.net/danapylayeva/user-story-mapping-workshop?qid=03fdb600-19a5-4610-9eb8-f9600f0bede2&v=&b=&from_search=15
comments:
product goals? ->personas-> user story mapping -> scrum sprint
Agile and user story workshop
http://www.slideshare.net/petersaddington/agile-and-user-story-workshop-peter-saddington?qid=754f9138-698f-4676-b8ee-7d546510d079&v=&b=&from_search=7
星期二, 10月 25, 2016
Word調整目錄及標號字型
- 目錄部份, 修改各層「目錄」相關樣式就可以了
- 標號部份,可於插入標號後,按ctrl+shift+s鍵叫出「目前」所在標號的樣式選單,再選「修改」樣式,去修改字型大小就好了。
星期六, 10月 15, 2016
psnr and ssim 好文章
1. Ji Life House: 圖片相似度----SSIM以及PSNR
http://jirongwu81.blogspot.tw/2016/09/ssimpsnr.html
2. 视频编码方案之间的比较(HEVC,H.264,MPEG2等)
http://www.cnblogs.com/xkfz007/p/4509746.html
3. 電機工程系碩士班碩士學位論文基於SSIM 之H.264 視訊傳輸服務品質
4. [參考] x264命令行參數解釋
https://www.ptt.cc/bbs/AVEncode/M.1305719689.A.615.html
5. Netflix 評估影片品質的方法
https://blog.gslin.org/archives/2016/06/08/6618/netflix-%E8%A9%95%E4%BC%B0%E5%BD%B1%E7%89%87%E5%93%81%E8%B3%AA%E7%9A%84%E6%96%B9%E6%B3%95/
6. H.264轉碼加速:NVENC大戰Quick Sync
http://www.gamez.com.tw/thread-568549-1-1.html
7. x264视频压制入门
http://blog.sorabbs.tk/archives/27
8. How to consider bitrate, -maxrate and -bufsize of a video for web
http://superuser.com/questions/945413/how-to-consider-bitrate-maxrate-and-bufsize-of-a-video-for-web
http://jirongwu81.blogspot.tw/2016/09/ssimpsnr.html
2. 视频编码方案之间的比较(HEVC,H.264,MPEG2等)
http://www.cnblogs.com/xkfz007/p/4509746.html
3. 電機工程系碩士班碩士學位論文基於SSIM 之H.264 視訊傳輸服務品質
4. [參考] x264命令行參數解釋
https://www.ptt.cc/bbs/AVEncode/M.1305719689.A.615.html
5. Netflix 評估影片品質的方法
https://blog.gslin.org/archives/2016/06/08/6618/netflix-%E8%A9%95%E4%BC%B0%E5%BD%B1%E7%89%87%E5%93%81%E8%B3%AA%E7%9A%84%E6%96%B9%E6%B3%95/
6. H.264轉碼加速:NVENC大戰Quick Sync
http://www.gamez.com.tw/thread-568549-1-1.html
7. x264视频压制入门
http://blog.sorabbs.tk/archives/27
8. How to consider bitrate, -maxrate and -bufsize of a video for web
http://superuser.com/questions/945413/how-to-consider-bitrate-maxrate-and-bufsize-of-a-video-for-web
星期一, 10月 10, 2016
Node.js Job Queue
Reference:
Kue, https://github.com/Automattic/kue
Document/Example:
https://www.linkedin.com/pulse/job-queue-nodejs-adrien-desbiaux
1. Install Redis
2. Install Kue
Usage:
Producer
1. 建立queue instance
var kue = require('kue'),
var jobs = kue.createQueue();
2. 建立job
job = jobs.create('bessel-filter-image', jobArgs).save();
3. 等待job 結束(callback)
job
.on('complete', function(result) { //whatever you want to do })
.on('failed', function() { console.log(job.id); });
Consumer:
1. 建立queue instance?
2. 處理job
3. 處理完呼叫done
jobs.process('bessel-filter-image', function(job, done) {
console.log(job.data.whatever); // stored in jobArgs
var result = bessel(); // let's imagine applying the filter
done(null, result); // forward the result of your job
});
更新Job Progress....
http://stackoverflow.com/questions/15375126/fetching-the-result-of-a-kue-job-and-pushing-this-to-the-client-over-open-connec
Kue, https://github.com/Automattic/kue
Document/Example:
https://www.linkedin.com/pulse/job-queue-nodejs-adrien-desbiaux
1. Install Redis
2. Install Kue
Usage:
Producer
1. 建立queue instance
var kue = require('kue'),
var jobs = kue.createQueue();
2. 建立job
job = jobs.create('bessel-filter-image', jobArgs).save();
3. 等待job 結束(callback)
job
.on('complete', function(result) { //whatever you want to do })
.on('failed', function() { console.log(job.id); });
Consumer:
1. 建立queue instance?
2. 處理job
3. 處理完呼叫done
console.log(job.data.whatever); // stored in jobArgs
var result = bessel(); // let's imagine applying the filter
done(null, result); // forward the result of your job
});
更新Job Progress....
http://stackoverflow.com/questions/15375126/fetching-the-result-of-a-kue-job-and-pushing-this-to-the-client-over-open-connec
actually this is covered in the documentation - https://github.com/LearnBoost/kue
"Job Events
Job-specific events are fired on the Job instances via Redis pubsub. The following events are currently supported:
failed
the job has failedcomplete
the job has completedpromotion
the job (when delayed) is now queuedprogress
the job's progress ranging from 0-100 For example this may look something like the following:var job = jobs.create('video conversion', { title: 'converting loki\'s to avi' , user: 1 , frames: 200 }); job.on('complete', function(){ console.log("Job complete"); }).on('failed', function(){ console.log("Job failed"); }).on('progress', function(progress){ process.stdout.write('\r job #' + job.id + ' ' + progress + '% complete'); });
bare in mind that your job might not be processed immediatly (depends on your queue), so the client can wait some time for a result..
EDIT: as mentioned in the comments, a job doesn't return any results so you should store the result in the database along with the job id and query the database when the job is complete.
in order to keep the connection open, use
res.write
and res.end
instead of res.json
which ends the connection (You'll have to JSON.stringify
the data yourself). also, remember that the browser can timeout if this takes too long..Updating Progress
For a "real" example, let's say we need to compile a PDF from numerous slides with node-canvas. Our job may consist of the following data, note that in general you should not store large data in the job it-self, it's better to store references like ids, pulling them in while processing.
queue.create('slideshow pdf', {
title: user.name + "'s slideshow"
, slides: [...] // keys to data stored in redis, mongodb, or some other store
});
We can access this same arbitrary data within a separate process while processing, via the
job.data
property. In the example we render each slide one-by-one, updating the job's log and progress.queue.process('slideshow pdf', 5, function(job, done){
var slides = job.data.slides
, len = slides.length;
function next(i) {
var slide = slides[i]; // pretend we did a query on this slide id ;)
job.log('rendering %dx%d slide', slide.width, slide.height);
renderSlide(slide, function(err){
if (err) return done(err);
job.progress(i, len, {nextSlide : i == len ? 'itsdone' : i + 1});
if (i == len) done()
else next(i + 1);
});
}
next(0);
});
Node.js Job Queue
Reference:
Kue, https://github.com/Automattic/kue
Document/Example:
https://www.linkedin.com/pulse/job-queue-nodejs-adrien-desbiaux
1. Install Redis
2. Install Kue
Usage:
Producer
1. 建立queue instance
var kue = require('kue'),
var jobs = kue.createQueue();
2. 建立job
job = jobs.create('bessel-filter-image', jobArgs).save();
3. 等待job 結束(callback)
job
.on('complete', function(result) { //whatever you want to do })
.on('failed', function() { console.log(job.id); });
Consumer:
1. 建立queue instance?
2. 處理job
3. 處理完呼叫done
jobs.process('bessel-filter-image', function(job, done) {
console.log(job.data.whatever); // stored in jobArgs
var result = bessel(); // let's imagine applying the filter
done(null, result); // forward the result of your job
});
更新Job Progress....
http://stackoverflow.com/questions/15375126/fetching-the-result-of-a-kue-job-and-pushing-this-to-the-client-over-open-connec
https://github.com/Automattic/kue#job-progress
Kue, https://github.com/Automattic/kue
Document/Example:
https://www.linkedin.com/pulse/job-queue-nodejs-adrien-desbiaux
1. Install Redis
2. Install Kue
Usage:
Producer
1. 建立queue instance
var kue = require('kue'),
var jobs = kue.createQueue();
2. 建立job
job = jobs.create('bessel-filter-image', jobArgs).save();
3. 等待job 結束(callback)
job
.on('complete', function(result) { //whatever you want to do })
.on('failed', function() { console.log(job.id); });
Consumer:
1. 建立queue instance?
2. 處理job
3. 處理完呼叫done
console.log(job.data.whatever); // stored in jobArgs
var result = bessel(); // let's imagine applying the filter
done(null, result); // forward the result of your job
});
更新Job Progress....
http://stackoverflow.com/questions/15375126/fetching-the-result-of-a-kue-job-and-pushing-this-to-the-client-over-open-connec
actually this is covered in the documentation - https://github.com/LearnBoost/kue
"Job Events
Job-specific events are fired on the Job instances via Redis pubsub. The following events are currently supported:
failed
the job has failedcomplete
the job has completedpromotion
the job (when delayed) is now queuedprogress
the job's progress ranging from 0-100 For example this may look something like the following:var job = jobs.create('video conversion', { title: 'converting loki\'s to avi' , user: 1 , frames: 200 }); job.on('complete', function(){ console.log("Job complete"); }).on('failed', function(){ console.log("Job failed"); }).on('progress', function(progress){ process.stdout.write('\r job #' + job.id + ' ' + progress + '% complete'); });
bare in mind that your job might not be processed immediatly (depends on your queue), so the client can wait some time for a result..
EDIT: as mentioned in the comments, a job doesn't return any results so you should store the result in the database along with the job id and query the database when the job is complete.
Job progress is extremely useful for long-running jobs such as video conversion. To update the job's progress simply invoke
job.progress(completed, total [, data])
:job.progress(frames, totalFrames);
data can be used to pass extra information about the job. For example a message or an object with some extra contextual data to the current status.
星期三, 9月 21, 2016
Android 的webview替代方案
在開發android中的web app時,會發現內建的webview或 browser效能不佳而且不支援比較新的html標準及功能,這時候可以選擇替代方案crosswalk. crosswalk是基於chrome browser的元件,可用在webview或 codorva中替代原生browser,提供更好的效能。
https://crosswalk-project.org/documentation/android/android_target_setup.html
https://crosswalk-project.org/documentation/android/android_target_setup.html
星期五, 9月 16, 2016
Git Reset, Checkout, and Revert
REF:
https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/summary
* Git Checkout
Q: 寫程式常常會覺得某一個版本寫的code是比較好,想從某個commit再重寫新版本,要如何做?
1. 可以用git checkout把某個commit 的code調出來檢視,由於此時HEAD指向該commit,不屬於任何branch,如果從這版本有修改新的程式碼,會造成不屬於任何branch,這些修改就算有commit,之後切到其它branch,所有改的內容也會遺失。
2. 解決方式: 1. 可以用git checkout把某個commit 的code調出來檢視,接著建立新的branch,check out到這branch後,再開始修改 code,把新的code套用commit在這新的branch後,就可以解決這問題。
ref: https://www.atlassian.com/git/images/tutorials/advanced/resetting-checking-out-and-reverting/05.svg
1. 有時候改的程式碼不小心commit或加到staged,用這指令可以把staged及commit的檔案全部變成unstaged,還原原始狀態。git reset --hard會把所有的檔案還原到最近一次commit的狀態,使用者任何修改過的檔案及狀態都會被移除。
2. 可以用來把某commit的程式碼全部移除掉,會造成該commit之後的其它commit也會被移除救不回,要小心使用。
REF:https://www.atlassian.com/git/images/tutorials/advanced/resetting-checking-out-and-reverting/02.svg
*Git Revert
1. 有時候過了很久才發現某改commit的程式碼改錯了,某個function不能用,但是之後的程式碼改很多,又不想重寫,可以用revert指令。
2. Git Revert指令有點像先刪除某個commit所作的動作,再套用該commit之後其它commits的變更,然後建立新commit。
REF: https://www.atlassian.com/git/images/tutorials/advanced/resetting-checking-out-and-reverting/06.svg
星期二, 8月 09, 2016
fat32在windows 10下格式化工具
http://macrorit.com/partition-magic-manager/free-edition.html
Permanently Free Expert-level Disk Partition Magic Software
免費,容易使用,可格式化超過32GB的記憶卡
Permanently Free Expert-level Disk Partition Magic Software
免費,容易使用,可格式化超過32GB的記憶卡
星期五, 8月 05, 2016
在ubuntu中disable apache2的方法
1. 最簡單的方法,安裝rcconf
sudo apt-get install rcconf
執行rcconf後,直接設定即可
2. 記得停止目前在執行的apach2
sudo service apach2 stop
sudo apt-get install rcconf
執行rcconf後,直接設定即可
2. 記得停止目前在執行的apach2
sudo service apach2 stop
星期六, 7月 30, 2016
node js 心得
1. 非同步可用promise來想辦法讓程式比較容易撰寫
Good Reference:
JavaScript Promise迷你书
http://liubin.org/promises-book/
2. javascript 中的this,跟 C#, Java, C++的使用方法有很大的差異。傳統物件導向程式語言是先定義好類別才建立物件,而javascipt的特性則是可先建立好物件才延展該物件功能。在javascipt中的this是代表呼叫特定函式的左邊.物件。如
var book = {};
function setPrice(price) {
this.price =price;
}
book.setPrice(100)時,
這時候this就代表為book物件,
setPrice(100);
可是如果直接呼叫setPrice(100)時,這時候this 就不存在
3. 如果function裡面有callback,由於callback中的this代表的會是呼叫該callback的物件,而不是外圍的instance物件,此時會導致 this 不存在。解法通常是在callback外面宣告一變數,利用變數域範圍的特性,來讓callback函式也可參考到同一物件。
function setPrice(price) {
var self =this;
onEvent('event', callback() {
self.result =xxx;
}
}
4. module心得,'json-socket'很好用,可快速處理訊息
Good Reference:
JavaScript Promise迷你书
http://liubin.org/promises-book/
2. javascript 中的this,跟 C#, Java, C++的使用方法有很大的差異。傳統物件導向程式語言是先定義好類別才建立物件,而javascipt的特性則是可先建立好物件才延展該物件功能。在javascipt中的this是代表呼叫特定函式的左邊.物件。如
var book = {};
function setPrice(price) {
this.price =price;
}
book.setPrice(100)時,
這時候this就代表為book物件,
setPrice(100);
可是如果直接呼叫setPrice(100)時,這時候this 就不存在
3. 如果function裡面有callback,由於callback中的this代表的會是呼叫該callback的物件,而不是外圍的instance物件,此時會導致 this 不存在。解法通常是在callback外面宣告一變數,利用變數域範圍的特性,來讓callback函式也可參考到同一物件。
function setPrice(price) {
var self =this;
onEvent('event', callback() {
self.result =xxx;
}
}
4. module心得,'json-socket'很好用,可快速處理訊息
星期日, 5月 29, 2016
Git 使用心得及記錄
0. 本地Commit有誤時,如何處理?
=>用reset
解法:
1. git reset --mixed (預設), repo的commit會取消,目前workspace己修改的檔案內容會保留,(就是好像退回到連add都沒做的狀態,好像什麼事都沒發生)
2. git reset --soft, repo的commit會取消,stage中會保持該取消的commit中的變更資料,(就是好像退回到原add的動作)。
3. git reset --hard, repo的commit會取消,會把workspace目前修改的檔案刪除,worksapce中的檔案會回到前一次commit的內容,所有這次改的資料都會不見。
可參考影片: https://www.youtube.com/watch?v=gVByWjwetVc
1. 如果不小心把本地端檔案殺掉了,但是reposity之前有儲存,要如何救回來?很簡單,就再從reposity checkout就好了。
2. Check out 會不會把目前目錄下的資料全部清除?
答案是會全把舊的資料全殺光,所以checkout之前要記得先commit或備份,以免損失慘重。
3. 把檔案用git add加到stage後,在workspace再修改,此時再commit時,檔案會用那個版本的?
Ans: 檔案會用staged的版本。workspace修改的版本或資料並不會commit進去。
(If I modify a file that is added, and retry the commit, the changes aren't recognized, so the commit will fail again.)
解決方法1: 再用git add重做一次就好
解決方法2: 先用預設 reset的命令(--mixed),取消stage的動作(此時不會覆蓋workspace的版本),再重新commit就好。
注意: 千萬不要亂下git reset -hard,會把workspace目前修改的檔案刪除
https://stackoverflow.com/questions/27776588/modifying-a-file-after-git-add
http://lib.csdn.net/article/git/28621
=>用reset
解法:
1. git reset --mixed (預設), repo的commit會取消,目前workspace己修改的檔案內容會保留,(就是好像退回到連add都沒做的狀態,好像什麼事都沒發生)
git reset HEAD file
( which by default is using the --mixed
flag) is different in that in the case where the file is already in the repo, it replaces the index version of the file with the one from repo (HEAD), effectively unstaging the modifications to it.3. git reset --hard, repo的commit會取消,會把workspace目前修改的檔案刪除,worksapce中的檔案會回到前一次commit的內容,所有這次改的資料都會不見。
可參考影片: https://www.youtube.com/watch?v=gVByWjwetVc
1. 如果不小心把本地端檔案殺掉了,但是reposity之前有儲存,要如何救回來?很簡單,就再從reposity checkout就好了。
2. Check out 會不會把目前目錄下的資料全部清除?
答案是會全把舊的資料全殺光,所以checkout之前要記得先commit或備份,以免損失慘重。
3. 把檔案用git add加到stage後,在workspace再修改,此時再commit時,檔案會用那個版本的?
Ans: 檔案會用staged的版本。workspace修改的版本或資料並不會commit進去。
(If I modify a file that is added, and retry the commit, the changes aren't recognized, so the commit will fail again.)
解決方法1: 再用git add重做一次就好
注意: 千萬不要亂下git reset -hard,會把workspace目前修改的檔案刪除
https://stackoverflow.com/questions/27776588/modifying-a-file-after-git-add
http://lib.csdn.net/article/git/28621
星期三, 5月 25, 2016
docker install on ubuntu 14.04
- 根據install guilde (https://docs.docker.com/linux/)安裝後
$ curl -fsSL https://get.docker.com/ | sh
要記得重開機,之後執行畫面如下:
表示執行成功。
2.下載container with nodejs and ffmpeg
docker pull dkarchmervue/fluent-ffmpeg
下載container, 由於docker的檔案架構是一層一層建上去的,所以會一層一層下載後建立image。如果有多個container引用相同image來建置,則可共用相同來源的layer,節省儲存空間。
docker run --rm -ti -v ${PWD}:/work dkarchmervue/fluent-ffmpeg node your-nodejs-script.js
參數說明:
--rm: container結束後,就移除所有container內的資料。 (預設情況下,container結束後,資料會存在container中,container預設空間為10G)
--ti: 產生虛擬tty,跟container互動
-v: 資料目錄映設,將主機的目錄與container中的mount point映射,此例為${PWD}目前工作目錄映射到container中的/work目錄,container中任何資料寫入/work目錄,實際上會寫回主機目前工作目錄。
$ docker run -p 127.0.0.1:80:8080 ubuntu bash
This binds port 8080 of the container to port 80 on 127.0.0.1 of the host machine. The Docker User Guide explains in detail how to manipulate ports in Docker.
VS Code的環境設定
要讓VS Code很好用,建議先進行下列環境設定
Node.js Applications with VS Code
https://code.visualstudio.com/Docs/runtimes/nodejs
把jsconfig.json及typescript安裝好後,就比較好用了。
星期一, 4月 25, 2016
星期三, 4月 13, 2016
ffmpeg gop 大小 x264 設定
http://superuser.com/questions/908280/what-is-the-correct-way-to-fix-keyframes-in-ffmpeg-for-dash
Method 1: with libx264's arguments
-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1
#在壓x264時,有二個參數可以用來設定gop的大小,如果要設定成固定長度的gop,如每25個frame為一個GOP,則要把keyint 及 min-keyint設成同樣的值。
#在壓x264時,如果只設定keyint,則x264內定演算法scene_cut會偵測場景變化,選擇最有效率的I frame及GOP大小進行壓縮,此時,每個GOP的大小會是不定長度。
#scenecut=-1代表disable,則會採固定長度GOP進行壓縮,壓縮效率會比較差。
You should simply set the
Note that I am not assuming variable framerate sequences here. I honestly have no idea how to deal with those in practice—I honestly haven't come across any before.
To give you an example, I converted a clip three times:
As you can see, disabling scene cut detection and setting the keyframe interval is enough. It seems that even if you don't set a minimum, it'll insert keyframes at least at the interval specified by
I've researched this quite a bit a while ago—I'm currently involved in creating an ITU-T recommendation dealing with the analysis of DASH-type video transmission, so we had to figure out encoding settings that would be realistic, and from all of the documents and guides I've read, disabling scene cut detection and forcing the keyframe interval in x264 directly was the method of choice.
Method 1: with libx264's arguments
-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1
#在壓x264時,有二個參數可以用來設定gop的大小,如果要設定成固定長度的gop,如每25個frame為一個GOP,則要把keyint 及 min-keyint設成同樣的值。
#在壓x264時,如果只設定keyint,則x264內定演算法scene_cut會偵測場景變化,選擇最有效率的I frame及GOP大小進行壓縮,此時,每個GOP的大小會是不定長度。
#scenecut=-1代表disable,則會採固定長度GOP進行壓縮,壓縮效率會比較差。
You should simply set the
keyint
and min-keyint
to the same value and disable scene detection. If you don't disable
scene detection, the "counter" will indeed be reset, and your keyframes
end up at irregular intervals.Note that I am not assuming variable framerate sequences here. I honestly have no idea how to deal with those in practice—I honestly haven't come across any before.
To give you an example, I converted a clip three times:
keyint=25
(i.e., scenecut enabled)keyint=25:scenecut=-1
keyint=25:min-keyint=25:scenecut=-1
As you can see, disabling scene cut detection and setting the keyframe interval is enough. It seems that even if you don't set a minimum, it'll insert keyframes at least at the interval specified by
keyint
. To be safe you should probably set min-keyint
too.I've researched this quite a bit a while ago—I'm currently involved in creating an ITU-T recommendation dealing with the analysis of DASH-type video transmission, so we had to figure out encoding settings that would be realistic, and from all of the documents and guides I've read, disabling scene cut detection and forcing the keyframe interval in x264 directly was the method of choice.
Thank you! This is great
feedback. One question I have is how you generated that awesome table. I
could totally use something like that.
– Mark Gerolimatos
Apr 30 '15 at 21:39
(There appears to be no way
to write you directly) Can you please point me towards links to any
threads in this ITU-T discussion? Thanks!
– Mark Gerolimatos
Apr 30 '15 at 21:45
1 |
I just made that in Excel, pasting the output I got from three runs of
ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type
,
then coloring the cells. I'm afraid there are no public discussions,
but I'll see if I can dig up some of the links I found back then.
– slhck
Apr 30 '15 at 22:01
Could you please re-try your experiment with the
-force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)
form? I just tried it and found that while there were extra I frames in
the stream, it DID seem to abide by my rule. A PERL program will follow
as an "answer", as you cannot apparently use markup in comments.
– Mark Gerolimatos
May 1 '15 at 1:08
Interesting. I believe it's
worth a separate "real" answer if you found out that it works. (Stack
Exchange sites aren't really good for this discussion-style reply.) The
last time I checked,
-force_key_frames
didn't work for me, and so I never tried it again. That was more than a year ago. Perhaps it was a bug. I'll try again soon.
– slhck
May 1 '15 at 8:00
The answer therefore seems to be:
Script for the
Here is a short PERL program I used to verify I-frame cadence based
on the output of slhck's ffprobe suggestion. It seems to verify that the
|
星期二, 4月 12, 2016
ffprobe 觀察video frame使用方法
1. 觀察frame編號(coded_picture_number),資料大小(pkt_size),編碼類型IPB(pict_type), 播放時間順(pkt_pts_time), 解碼時間順(pkt_dts_time)
ffprobe -select_streams v:0 -show_entries frame=coded_picture_number,pkt_size,pict_type,pkt_pts_time,pkt_dts_time video.mp4 -of compact > result.txt
觀察結果
#檔案result.txt
frame|pkt_pts_time=0.000000|pkt_dts_time=0.000000|pkt_size=13695|pict_type=I|coded_picture_number=0
frame|pkt_pts_time=0.033367|pkt_dts_time=0.033367|pkt_size=630|pict_type=P|coded_picture_number=1
frame|pkt_pts_time=0.066733|pkt_dts_time=0.066733|pkt_size=827|pict_type=P|coded_picture_number=2
frame|pkt_pts_time=0.100100|pkt_dts_time=0.100100|pkt_size=1832|pict_type=P|coded_picture_number=3
frame|pkt_pts_time=0.133467|pkt_dts_time=0.133467|pkt_size=367|pict_type=P|coded_picture_number=4
frame|pkt_pts_time=0.166833|pkt_dts_time=0.166833|pkt_size=1544|pict_type=P|coded_picture_number=5
2. 找出所有I畫面幀
cat result.txt | grep 'type=I'
觀察結果
frame|pkt_pts_time=0.000000|pkt_dts_time=0.000000|pkt_size=13695|pict_type=I|cod
ed_picture_number=0
frame|pkt_pts_time=2.002000|pkt_dts_time=2.002000|pkt_size=17793|pict_type=I|cod
ed_picture_number=60
frame|pkt_pts_time=3.636967|pkt_dts_time=3.636967|pkt_size=15824|pict_type=I|cod
ed_picture_number=109
frame|pkt_pts_time=5.638967|pkt_dts_time=5.638967|pkt_size=15158|pict_type=I|cod
ed_picture_number=169
frame|pkt_pts_time=7.640967|pkt_dts_time=7.640967|pkt_size=11380|pict_type=I|cod
ed_picture_number=229
frame|pkt_pts_time=9.642967|pkt_dts_time=9.642967|pkt_size=16336|pict_type=I|cod
ed_picture_number=289
ffprobe -select_streams v:0 -show_entries frame=coded_picture_number,pkt_size,pict_type,pkt_pts_time,pkt_dts_time video.mp4 -of compact > result.txt
觀察結果
#檔案result.txt
frame|pkt_pts_time=0.000000|pkt_dts_time=0.000000|pkt_size=13695|pict_type=I|coded_picture_number=0
frame|pkt_pts_time=0.033367|pkt_dts_time=0.033367|pkt_size=630|pict_type=P|coded_picture_number=1
frame|pkt_pts_time=0.066733|pkt_dts_time=0.066733|pkt_size=827|pict_type=P|coded_picture_number=2
frame|pkt_pts_time=0.100100|pkt_dts_time=0.100100|pkt_size=1832|pict_type=P|coded_picture_number=3
frame|pkt_pts_time=0.133467|pkt_dts_time=0.133467|pkt_size=367|pict_type=P|coded_picture_number=4
frame|pkt_pts_time=0.166833|pkt_dts_time=0.166833|pkt_size=1544|pict_type=P|coded_picture_number=5
2. 找出所有I畫面幀
cat result.txt | grep 'type=I'
觀察結果
frame|pkt_pts_time=0.000000|pkt_dts_time=0.000000|pkt_size=13695|pict_type=I|cod
ed_picture_number=0
frame|pkt_pts_time=2.002000|pkt_dts_time=2.002000|pkt_size=17793|pict_type=I|cod
ed_picture_number=60
frame|pkt_pts_time=3.636967|pkt_dts_time=3.636967|pkt_size=15824|pict_type=I|cod
ed_picture_number=109
frame|pkt_pts_time=5.638967|pkt_dts_time=5.638967|pkt_size=15158|pict_type=I|cod
ed_picture_number=169
frame|pkt_pts_time=7.640967|pkt_dts_time=7.640967|pkt_size=11380|pict_type=I|cod
ed_picture_number=229
frame|pkt_pts_time=9.642967|pkt_dts_time=9.642967|pkt_size=16336|pict_type=I|cod
ed_picture_number=289
星期二, 3月 29, 2016
Retrofit android restful https
Retrofit Android example | Web services using Retrofit
http://www.androidwarriors.com/2015/08/retrofit-android-example-web-services.html
Retrofit Android Tutorial to Get JSON from Server
Android Studio Parsing Json Using Retrofit
Retrofit — Basic Authentication on Android
https://futurestud.io/blog/android-basic-authentication-with-retrofit
Make Your First Android App: Part 3/3
https://www.raywenderlich.com/56111/make-first-android-app-part-3
http://www.androidwarriors.com/2015/08/retrofit-android-example-web-services.html
Retrofit Android Tutorial to Get JSON from Server
Android Studio Parsing Json Using Retrofit
Retrofit — Basic Authentication on Android
https://futurestud.io/blog/android-basic-authentication-with-retrofit
Make Your First Android App: Part 3/3
https://www.raywenderlich.com/56111/make-first-android-app-part-3
星期一, 3月 28, 2016
User Story Good Articles
用户故事驱动的敏捷开发 – 1. 规划篇
http://devopshub.cn/2016/02/28/user-story-driven-agile-development-1-planning/
http://geek.csdn.net/news/detail/63625
http://devopshub.cn/2016/01/10/user-story-mapping-for-the-first-time/
http://devopshub.cn/2016/01/11/how-to-create-user-story-mapping/
http://devopshub.cn/2016/02/28/user-story-driven-agile-development-1-planning/
http://geek.csdn.net/news/detail/63625
http://devopshub.cn/2016/01/10/user-story-mapping-for-the-first-time/
http://devopshub.cn/2016/01/11/how-to-create-user-story-mapping/
星期六, 3月 26, 2016
在ubutnu 14.04安裝ffmpeg
http://www.faqforge.com/linux/how-to-install-ffmpeg-on-ubuntu-14-04/
sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install ffmpeg
Why redirect output to 2>&1 and 1>&2?
Why redirect output to 2>&1 and 1>&2?
http://superuser.com/questions/436586/why-redirect-output-to-21-and-12
簡單的說,就是把stderr(2) 轉向到stdout(1), 讓一些命令可以進一步處理,例如grep就只能讀stdout的資料,如果我們想處理stderr的結果,就要2>&1
另外一種情況是想把stderr的錯誤也記錄下來到同一檔案, 可以一樣的做法。
http://superuser.com/questions/436586/why-redirect-output-to-21-and-12
簡單的說,就是把stderr(2) 轉向到stdout(1), 讓一些命令可以進一步處理,例如grep就只能讀stdout的資料,如果我們想處理stderr的結果,就要2>&1
另外一種情況是想把stderr的錯誤也記錄下來到同一檔案, 可以一樣的做法。
ns2 codelite debug gdb ubutnu 14.04 Setting
- Create Project using Project Wizard, and then select custom Makefile since we already have one in ns-2.35 directory
- Go to project setting to set the working directory
- Remember to modify Makefile add -g setting for debug
- Enable gdb debug, then you can add breakpoint like visual studio.
- Remember to right click the project, and select to "Import File(Directorys)...", in the filter, remember to add "*.cc;*.tcl" to add cc and tcl scripts
http://stackoverflow.com/questions/7832892/how-to-change-the-default-gcc-compiler-in-ubuntu/7834049#7834049
http://stackoverflow.com/questions/14997275/gdb-and-ns2-how-to-stop-program-at-some-function-call
星期三, 2月 17, 2016
H.264 SPS, PPS, Slice, MB主要資訊
SPS(Sequence Parameter Set)主要描述影片串流的資訊,此外也包含vui的資訊:
- profile_idc: 代表視訊所用的H264 Profile,如 Base, Extension, High Profile。codec會根據profile來初始化一些參數。
- pic_order_cnt_type: 代表計算圖片顯示順序(Picture Order Count, POC)所採用的方式 (POC Type)。大部分為零。
- log2_max_frame_num_minus4: 代表畫面幀的最大數字((值+4)*2)。在解碼時,會有緩衝區用來儲存I, P參考幀,該緩衝區會重覆使用。每個畫面幀在解碼時會有一個frame_num數字,代表該畫面於解碼緩衝區id。
- pic_width_in_mbs_minu1: 畫面幀的寛度,以microblock為單位。
- pic_height_in_map_units_minus1: 畫面幀的高度,以map unit為單位?。
- direct_8x8_inference_flag: 描述mv預測方式。
- vui:
- num_units_in_tick: 時間單位
- time_scale: 每個時間單位播幾張畫面
PPS(Picture Parameter Set)主要描述畫面幀(或field場)資訊:
- pic_parameter_set_id: PPS的id,在一個影片中會有很多畫面幀或片段(Slice),這些畫面片段會參考PPS的設定進行編解碼。
- seq_parameter_set_id: 目前PPS所參考到的SPS id。
- entropy_coding_mode_flag: 畫面幀壓縮方法,如1代表CABAC。
Slice Header:
- first_mb_in_slice: 第一個mb在slice中的位置,通常為0。
- slice_type: Slice的類型,如 I, P, B frame/slice
- frame_num: 在緩衝區的frame id
MicroBlock:
星期二, 2月 16, 2016
CodeLite使用補充
- 安裝cscope
https://github.com/eranif/codelite/issues/795
- 假如程式碼不需要build只想要查尋原始source code,則可匯入舊的程式碼,如library。(忽略custom build, 如果是用msys2等,直接打開shell 在msys2下make編譯library就好,不要再codelite中設定)。
假設舊的程式碼在
D:\TestArea\MyCustomProject
and uses makefile
for the build process.
The fastest way to import this project into CodeLite is:
- Create a new project Workspace -> Create New Project give it any name and place it under
D:\TestArea\MyCustomProject
( you can check the option 'create the project under a separate directory' )
- Right-click on the project, and select Import Files From Directory. The import dialog will pop up; accept its defaults and click OK. (匯入不會把檔案複製一遍,原檔案還是會留在原來的地方)
- Once the import process completes, you can expand the tree to the left, where you should see all source files imported from the disk.
- You can add / delete any targets from the Project Settings -> Customize >Custom Build , the below screenshot shows how to add a cmake target
ffmpeg parser libx264資料
- FFMPEG结构体分析:AVFormatContext
http://blog.csdn.net/leixiaohua1020/article/details/14214705
- 使用FFMPEG类库分离出多媒体文件中的H.264码流
http://blog.csdn.net/leixiaohua1020/article/details/11800877
- FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分
http://blog.csdn.net/leixiaohua1020/article/details/45001033
- 最简单的视频编码器:基于libx264(编码YUV为H.264)
http://blog.csdn.net/leixiaohua1020/article/details/42078645
- 下載x264 程式碼
- git clone git://git.videolan.org/x264.git
- 下戴yasm
http://yasm.tortall.net/Download.html - 改名字,並複製到d:\msys64\usr\bin\yasm.exe.
YASM Setup
Download YASM executable from http://yasm.tortall.net/Download.html. You have to download the "general use" binaries and NOT the ones for VS2010. Either Win32 or Win64 binaries support outputting object files for both architectures so that should not matter. The last tested version was yasm-1.3.0-win64.exe.
Rename the downloaded executable to yasm.exe and place it in your MSYS2 path. E.g.C:\msys64\usr\bin\yasm.exe.
- 到codelite設定一下路徑
- 問題: codelite中,debugger有時候會不work,到設定中修改automatically set...就可以除錯
- 問題: 在編譯完後執行後產生不出來h264檔案,x264_encoder_encode函式傳回值為0, pNals, iNal值也為0,原因為多執行緒 delay encode的問題,如下:
http://blog.sina.com.cn/s/blog_51396f890102f061.html
到程式39行,新增一行
pParam->i_threads = 1;
強制thread為1就解決delay encode的問題,但是效能會比較差。
星期一, 2月 15, 2016
NALU h.264 相關資料
Concept:
一步一步解析H.264码流的NALU(SPS,PSS,IDR)
- Exploring H.264. Part 2: H.264 Bitstream format
http://gentlelogic.blogspot.tw/2011/11/exploring-h264-part-2-h264-bitstream.html
一步一步解析H.264码流的NALU(SPS,PSS,IDR)
http://guoh.org/lifelog/2013/10/h-264-bit-stream-sps-pps-idr-nalu/
- 解讀h264 SPS的參考資料
The h.264 Sequence Parameter Set
https://cardinalpeak.com/blog/the-h-264-sequence-parameter-set/
- IDR介紹
http://www.programgo.com/article/73452314422/
- 如何区分H.264视频流的I frame 和 P frame
http://www.yaosansi.com/post/how-to-distinguish-between-I-frame-and-P-frame-H264-video-streams/
- x264命令行參數解釋
https://www.ptt.cc/bbs/AVEncode/M.1305719689.A.615.html
- tool to extract H.264 frame size vector
http://forum.doom9.org/showthread.php?t=149122
- ffprobe showframes 再結合awk或其它工具,就可以抓frame的資訊
https://trac.ffmpeg.org/wiki/FFprobeTips
MSVC 使用linux C Library的方法
Microsoft Visual C++可以使用linux 有source code 的函式庫,如libjpeg等,方法如下:
- 利用mingw 編譯liunx library,產生.a 及dll
- 利用gcc 產生def檔, e.g.,
gcc -shared -o your_dll.dll your_dll_src.c -Wl,--output-def,your_dll.def
- 利用MSVC的工具lib.exe ,結合dll及.def 檔轉換成.lib檔,之後就可以在vc內使用
lib /def:your_dll.def
Note: 只能轉換C library,不能轉換C++ Library,因為gcc 跟 msvc在處理C++ Library的方式不相容,所以只能轉換C 函式庫
如何在vc內使用c lib?
例子:
extern "C" {
include "openssl.h"
}
Reference:
- How to use libraries compiled with MingW in MSVC?
http://stackoverflow.com/questions/2529770/how-to-use-libraries-compiled-with-mingw-in-msvc
訂閱:
文章 (Atom)