2017年2月12日 星期日

3DP : 用 G92 來設定目前的座標

3D printer 在開始輸出東西前,一般會利用「G28」的 Gcode 來讓各軸回到「Home」,馬達會運轉到觸發限位開關才停止,以此來當作計算座標的參考。以我的 Prusa i3 採用笛卡兒座標系統,當三軸的限位開關被觸發時,就當作那裡是零,其它位置的座標,就能依各軸旋轉的相關參數來計算。

3D printer 是由噴頭擠料塑形,座標看噴頭位置就好;但是如果將雷射裝在 3D printer 上,位置和被雷射的物體怎麼放又有很大的關係了。我本來是利用兩枝大冰棒棒做了一個呈九十度夾角的 L 形定位輔助,利用雷射弱光來定位,將輔器放在原點的位置以後,最後再用夾字來固定。這樣子就可以很快的將物件放到定點上。不過,用久了,還是會跑掉;有時則可能是物件形狀的問題,造成燒錯位置,尤其是小件的物品,差一點點就差很多了。後來懶得再去調 L 形輔具了,索性改用 Gcode 裡的「G92 」,直接告訴控制系統,那裡的座標是多少。

「G92」我之前拿來調整電容式近接開關的參數,記錄在底下的舊文中:



當時是針對 Z 軸,這回是應用在 X / Y 軸上。

例如要雷射的物件是一個直徑 12mm 的圓柱體,當我將東西放好,執行移動到圓柱圓心位置 (X=6, Y=6) 的指令:

G0 X6 Y6 F500

結果發現雷射並沒有剛好打在圓心上,於是以手動的方式慢慢移動 X / Y 軸的馬達,讓雷射能落在圓心上。

好~那怎麼讓系統知道那裡才是我們圓心的座標 (X=6 , Y=6) 呢?

換主角出場囉!執行底下的 Gcode :

G92 X6 Y6

我將這指令翻譯一下:「報告系統,請記住,這裡是 X=6,Y=6,Over!」。

接下來,機器會以此去推算其它位置了。

還記得第一次玩 Grbl 時,因為沒有限位開關,機器總是以開機的位置當 Home,搞不清楚它的座標系統,常讓馬達轉過頭。有了這個「G92」就方便多了。

不過要注意的是:

  • G92 後面如果都沒加參數的話,系統會當你是要執行「G92 X0 Y0 Z0 E0」哦!

G92 的詳細用法可以參考 Reprap 網站上的資料:





2017年2月8日 星期三

Inkscape : J Tech Photonics Laser Tool 換解析度

Inkscape 0.92 預設使用 96 DPI,這讓以前針對 90 DPI 設計的 Extensions 會有非預期的結果。當然啦!文件設定不好也有會有類似的情形發生。所以如果想使用 GcodeTools 一系列的 Gcode 轉換工具,在 Inkscape 0.92 版中,開始畫圖之前,記得先在「文件屬性」裡,將「Display units」設為使用「px」當單位,並將「比例」中的 X scale 設為「1」。此部份可以參考我的另一篇記錄:

可是光這樣還不夠,像  J Tech Photonics Laser Tool 這個 Extension,當初它是針對 90DIP 來寫的,匯出的 Gcode 輸出的圖形尺寸會不對。GcodeTools 的另一個「後代」Mr Beam gcode generators 比較跟得上時代,它就提供了換 DPI 的選項。

花了一點時間,將 Mr Beam 有關設置 Orientation 的程式片段,轉移到 J Tech Photonics Laser Tool  中,讓它也可能根據 Inkscape 的版本來設定 DPI。

另外也順便把 J Tech Photonics Laser Tool 中的一些些臭蟲給除了。修改過的檔案可以在下面的網址中下載:

備註:
修改的 J Tech Photonics Laser Tool 源自於「J Tech Photonics, Inc.」網站所分享的,最原始的程式可以由該單位的網站中下載:
https://jtechphotonics.com/

相關文章




2017年2月7日 星期二

Python : zero length field name in format

將一個可以在 Inkscape 0.92 正常執行的 Extension 放到 Inkscape 0.91 中卻出現以下的錯誤訊息:

comment = ";Image: {:.2f}x{:.2f} @ {:.2f},{:.2f}|".format(w,h,x,y) + file_id+"\n"
ValueError: zero length field name in format

因為兩個不同版本的 Inkscape 內建不同的版本的 Python,一個是 Python 2.7,另一個則是 Python 2.6 ,這又是改版以後產生的問題。

自 Python 2.7 以後,format 的格式可以不用指定參數的序號,例如:

{} {} {}

會自動對應 format 的參數一、參數二、參數三,但是這樣的格式在在舊版的 Python 2.6 中要改成:

{0} {1} {2}


所以將原來有錯的地方改為:

{0:.2f}x{1:.2f} @ {2:.2f},{3:.2f}|

錯誤訊息就消失了。




Inkscape : 更新 Python 的 PIL

Inkscape 的 Extensions 使用到 Python,因此它在安裝時已自帶 Python。我們可以在 Inkscape 的安裝目錄中找找,應該會看到一個名稱為「Python」的資料夾。但是不同版本的 Inkscape 可能內建不同版本的 Python;像 v.0.91 用的是 Python 2.6,而 v.0.92 用的確是較新的 Python 2.7。

除此之外,Python 內所擁有的程式庫當然也有所不同。最近在研究一個 Inkscape 的 Extension,它使用到一支 image2gcode.py ,而裡面又使用到 PIL 的 Image,無論在 Inkscape 0.92 或是 0.91 它都會出現這樣的訊息:

...... in __getattr__raise ImportError("The _imaging C module is not installed")
ImportError: The _imaging C module is not installed

由訊息看起來,應該是 PIL 少了類似 _imaging.pyd _imaging.dll ...... 這種檔名為 _imaging.xxx 的模組檔案。不過,查了一下 Inkscape\python\Lib\site-packages\PIL 目錄,裡面確定有 imaging.pyd 這個檔案啊!在 Inkscape 的 PIL 目錄中看到有一個檔案叫「PIL-1.1.6-py2.5.egg-info」,1.1.6 應該是 PIL 的版本序號,而 py2.5 是給 Python 1.5.2 以後的版本用的。

冤有頭,債有主,既然是 PIL 的問題,就試著把它換掉看看。

2017年2月6日 星期一

Inkscape : SVG 頁面設定與圖形大小

年前找出在 Flash 中設計的頭像圖,實驗性的匯出成為 .AI 格式的向量圖,並以「UniConvertor」轉為 SVG 檔,最後才能在 Inscape 中編輯。有人可能要問我:「為什麼不直接以 Inscape 來開啟 .AI 檔案?它有支援啊!」哈!因為我是用 Flash 8 ,它太舊了,只能匯出舊版的 AI 格式,就那麼剛好,Inkscape 不支援太舊的 .AI 檔。

當時發現一個問題,同樣都可以處理向量圖形,Flash 匯出的圖在 Inkscape 中就是特別的小,當時在玩別的東西,也沒深究。這幾天在研究幾個 SVG 轉 G-code 的工具,發現這問題可是大問題了,如果用的是 GcodeTools、J Tech Photonics Laser Tool、Mr Beam、TurnkeyLaser Exporter ......,這些以 GcodeTools 為架構的 Extensions,因為 SVG 的設計,有些圖檔轉出的圖形大小實在差太多了。如果對 SVG 圖形的縮放有興趣,可以參考底下的文章,研究看看:


基本上是這樣的概念:點陣圖向來就是一個點、一個點畫在版面中,版面怎麼縮放,點就跟著縮放;但對於 SVG 的向量圖來說,「單位」很重要,放大、縮小版面,向量圖本體卻可能因「單位」是用 px、mm、in ...... 而有所差異,一定要弄清楚。

Inkscape 0.92 將預設的 DPI 由 90 改為 96,對一些和尺寸有關的 Extensions 應該會有所影響,因為這一改,比例、位置都可能會跑掉了。

  • v.0.91 的 90DPI : 1mm = 90/25.4 = 3.5433070660 px
  • v.0.92 的 96DPI : 1mm = 96/25.4 = 3.7795275591 px

如果以 Inkscape 0.92 來開啟舊版儲存的文件,將文件屬性中的「Display units」由「px」和「mm」之問切換,應該可以在「比例」中的「Scale x」中看到 3.xxxxx 的數字。

下面直接在 Inkscape 0.92 裡實驗,最後我們再來看看,操作 GcodeTools 一系列轉 G-code 的工具到底要先將 Inkscape 的頁面設定為什麼。

2017年2月3日 星期五

用 StippleGen 2 將照片轉為「點點畫」

用關鍵字「halftone cnc」,想找有沒有可以將照片轉為適合雷射的工具,看到底下的網頁在介紹「StippleGen2」:


深深地被它強大的功能吸引到,它利用大小不同的空心圓或是連續的線條來取代原圖中各點的顏色,轉好的 Halftone 效果完全符合我的需求。果然玩 CNC 的人比雷射多得多,資源亦較豐富。

StippleGen2 可以在底下的網頁內下載:


StippleGen2


在 StippleGen2 中將照片圖檔載入以後,它依使用者設定的「Stipples (點點數量)」、「Min. DOT SIZE (點點的最小尺寸)」、「DOT SIZE RANGE (點點的尺寸範圍)」、「WHITE CUT OFF (去掉較白的點)」......。

前面的這幾個選項,都可以利用拉桿來調整,至於什麼選項是做什麼用,拉拉看、調整一下大小,「等一會兒」,沒錯!就是要等一會兒,程式就會一次又一次的將「路徑」及圖像最佳化。

那些選項到底要怎麼搭配?這可能要看個人口味的輕重了。我要的是「點點分明」,所以會依照相的大小去調整 MIN. DOT SIZE,解析度不高的調小一點,反之,解析度高的就調大一點,總之,讓畫面中的點和點之間能有一些些留白,這樣子,不致於會因為重疊而讓雷射完的畫面焦黑一片。

至於點點的數量要設多少,「Stipples」設愈高,解析度當然愈高,不過,放到 Inkscape 去處理,或是轉 G-code 的時候會很耗系統資源和時間的。基本上,「Stipples」預設的 2000 ,對 30mm x 30mm 的相片來說,是品質與處理時間都可以接受的。不過,為了不浪費「Stipples」數量的限制,預先將相片「去背」應該會較好。

如果覺得畫面中的結果滿意了,我們可以按左下方的「SAVE STIPPLE FILE」或是「SAVE "TSP" PATH」將點點畫或是用線條來畫的 "TSP" PATH,儲存為 SVG 格式的向量圖檔。

如何在 Inkscape 中將 StippleGen2 製作的 stipple SVG 檔案轉為 G-code 呢?

首先,我們先開啟前面儲存好的「STIPPLE FILE」(*.svg),如果 Inkscape 是 0.91 以上的版本,因為 StippleGen2 儲存的格式是舊版的格式,Inkscape 會有對話框提示進一步要如何處理舊版格式所產生的問題,沒關係,按「Scale elements」就好。

按「Scale elements」自動調比例


進到 Inkscape 的編輯畫面,調整點點畫及頁面的尺寸大小:
  1. 先點選轉好的「點點畫」,更改它的寬度和高度為想要的大小
  2. 開啟設定「文件屬性」的對話框(按「檔案」→「文件屬性」)
  3. 按一下「將頁面調整成內容大小」的「加號」展開設定選項
  4. 按一下「將頁面調整成圖畫或選擇範圍的大小」。
  5. 關閉「文件屬性」的對話框,即完成尺寸的調整。
按「將頁面調整成內容大小」展開選單
按「將頁面調整成圖畫或選擇範圍的大小」



在 Inkscape 裡面將圖輸出 G-code 的工具(Extensions)有好幾個,像「Raster 2 Laser GCode generator」、「J Tech Photonics Laser Tool」、「Gcodetools」.....。

如果是用「Raster 2 Laser GCode generator」來轉 G-code,因為它都會將繪圖區中的畫面輸出為 PNG 的點陣圖,所以直接執行這個 Extension 轉換的程序即可。為了盡量保持圖的原始效果,我會選用以下的選項:

  • Resolution :「10 pixel/mm」
  • B/W conversion : 「B/W fixed threshold」


如果要體會一下 StippleGen2 幫我們計算好的「最佳路徑」,當然是要利用能轉向量圖的,所以我使用習慣用的「J Tech Photonics Laser Tool」來轉 G-code。

先將物件轉為「路徑」:
  1. 點選要轉 G-code 的「點點畫」或「"TSP" PATH」。
  2. 點選主選單「路徑」→「物件轉成路徑」。
將物件轉成路徑


將物件轉好路徑,我們就可以開始用「J Tech Photonics Laser Tool」來轉 G-code 了。

用「J Tech Photonics Laser Tool」以向量圖來轉好的處是在打雷射時較細膩,速度也滿快的,不過它轉檔的速度在我老舊的電腦上工作,實在是令人等得捶心肝啊!如果圖較大,而 stipples 多時,自己評估吧!




Inkscape : Extensions : 以線條填滿路徑

雷切時使用 「J Tech Photonics Laser Tool」 這個 Inkscape  extension 可以幫我們將向量圖形的框線變成雷射的「刀路」。不過它只能抓到框線而已,中間填滿的部份卻無法直接轉 G -code。之前找不到什麼替代的轉換工具,這兩天運氣不錯,試出了兩個工具可以幫我們將填色的部份用線條填滿。

GitHub evil-mad/EggBot 中的 Hatch fill :
GitHub KnoxMakers/KM-Laser 中的 Hatch fill :
GitHub cnc-club/gcodetools (Inkscape 已內建) 中的 Gcodetools_area (銑面) :

這三個 Inkscape extensions 都可以幫我將已轉為「路徑(path)」的圖形內,以線條來填滿。想看到填滿效果,

  1. 先將圖形轉為路徑,再使用工具。
  2. 將 Inkscape 的「檢視」→「顯示模式」改為「輪廓」。

Hatch fill

KM-Laser 的 Hatch fill 其實是源自於 EggBot ,所以它們的 Hatch fill 界面與操作是一樣的。
  • 將圖形轉為路徑 (path) : 先選取要處理的圖形以後,點選主選單「路徑 (Path)」中的「將物件轉為路徑 (Object to Path)」
  • 由 「擴充功能 (Extensions)」 的 「EggBot」或是「KM Laser」中點選「Hatch fill」。
  • 設定參數:有關參數的用途可以點選「More Info」的頁面參考,其中最重要的是「Hatch spacing」,它決定了填線條的密度,數字愈小,填得愈密。
  • 設定好參數,選取要填線條的圖,按一下「套用(Apply)」即可查看成果。

Gcodetools Area

Gcodetools 功能強大,而且 Inkscape 已內建,但是它操作起來比較繁鎖,光看到它一堆 CNC的專有名詞,就令人早早打了退堂鼓。我是在看了底下這個解說影片才又勾起研究的興趣的:

雖然 Gcodetools 的 Area 使用起來較繁鎖一點,不過它和前面兩個用直線填滿的演算法是不同的,也滿值得玩一玩的:
  • 將圖形轉為路徑 (path) : 先選取要處理的圖形以後,點選主選單「路徑 (Path)」中的「將物件轉為路徑 (Object to Path)」
  • 由 「擴充功能 (Extensions)」 的 「Gcodetools」 中選取「方向點 (Orientation points)」,加入「2-points mode」的「方向點」。
  • 由 「擴充功能 (Extensions)」 的 「Gcodetools」 選取「刀具庫 (Tools library)」,加入「電漿刀」(Tools type : plasma)。
  • 找到「電漿刀 (Plasma cutter)」的設定區塊後,選取 Inkscape 的文字工具來修改設定。最重要的設定是刀具的直徑「diameter」,也就是雷射光的粗細,它決定了用來填滿的線條粗細,可以先試試 0.1 。
  • 由 「擴充功能 (Extensions)」 的 「Gcodetools」 中選取「面銑 (Area)」,點選「面銑 (Area)」的頁面;設定「面銑刀具重疊 (Area tool overlap)」值為 0。另外兩個選項,「Area width」設為 1 ,而「Maximum area cutting curves」先用預設值,有時間可以慢慢玩玩,看不同設定值,效果有何差異。
  • 點選編輯區中要填滿的圖形以後,按「套用 (Apply)」,即可查看成果。


FAQ

  • Q: 使用 Gcodetools 時,加入了「電漿刀」,為什麼找不到 Plasma cutter 的設定區塊?
    A: 將版面的檢視比例縮小一點看看,它預設會放到很上面,如果放大檢視就看不到了。
  • Q: 如何利用 Gcodetools 來輸出 G-code ?
    A: 先將所有圖形都轉為「路徑」並選取好。
    在「Plasma cutter」中設定「feed」、「penetration feed」、「gcode before path」、「gcode after path」;
    然後進入「路徑轉為 Gcode」的 extensiion,設定
    「路徑轉為 Gcode」頁面中的「最大分割深 (Maximum splitting depth)」為 0,
    並勾選「排序路徑以減少高速距離 (Sort paths to reduse rapid distance)」;
    再設定「選項」頁面中的
    「沿著Z軸縮放 (Scale along Z axis)」(這個翻譯怪怪的,應該是沿著Z軸每次降低多少才對) 設為 0,
    「沿著Z軸偏移 (Offset along Z axis)」為起始的 Z 軸高度;
    最後回到「路徑轉為 Gcode」頁面,並按下「套用(Apply)」。




2017年1月2日 星期一

Biking : 烏塗窟

天氣狀況 : 晴
TRIP DIST : 34.60
TRIP TIME : 01:45:46
AVG. SPEED : 19.63
MAX. SPEED : 36.77

新年新希望,當然要破一下記錄,2016年破了騎乘最少的記錄,2017年的第二天就來擊倒它。哈~是說,這目標很容易達到啦!去年才騎了一趟稍有一點距離的,也還不到 30km。

今天試水溫,到北47指標 2km 處就折返。經過石碇老街,帶了大罐的豆漿、大袋的豆腐和三碗薑汁豆花。然後一路搖搖晃晃的騎回家,結束 2017 年的第一回。哦~吔~~一雙腿都乖乖的,希望他們能保持這樣,路還很長的!

2016年12月21日 星期三

Javascript : 小數位數失控

答應學生弄個二位小數的 PK 題庫,本以為很輕鬆的事,卻因為奇怪的小數位數問題而卡住。

本來想好的運算程序是:

  1. 設定要二位小數。
  2. 用亂數出一個三位數。
  3. 將三位數除以十的二次方。
程式碼大概這樣:

decimal_places = 2;
var factor = Math.pow(10, decimal_places); 
var tempRandom = tools.makeRandomIndex(1, factor-1);
var r = Math.floor(Math.random()*tempRandom.length);
var n1 = tempRandom[r]/factor;

註:上面的 tools.makeRandomIndex 是我用來產生兩個參數指定範圍內所有數,並打亂順序的自訂函數。

看起來沒問題,但當我用同樣的方法取出另一個數 n2,並將 n1 與 n2 相加的結果設給 answer 這個變數以後。有時卻會出現二位小數加上二位小數,產生比二位還多很多位的小數,而且答案雖然趨近於相加的結果,卻不是正確的。

一開始還懷疑是自己的演算程序有問題,除蟲除半天, toFixed() 和 toPrecision() 也搬出來用了,還是怪怪的。

廢話不多說,後來修改了一下程序:

decimal_places = 2;
var factor = Math.pow(10, decimal_places); 
var tempRandom = tools.makeRandomIndex(1, factor-1);
var r = Math.floor(Math.random()*tempRandom.length);
var n1 = tempRandom[r]; 
var tempRandom = tools.makeRandomIndex(1, factor-1);
var r = Math.floor(Math.random()*tempRandom.length);
var n2 = tempRandom[r]; 
var answer = (n1 + n2)/factor;

要給 answer 計算的 n1 和 n2 先不做除法(變成小數),等加完結果以後,再除10的二次方(本例中的 factor)。

程序調整以後,answer 的內容不會再出現小數多於二位的情形了。



2016年12月18日 星期日

LimeJS : frame.js Failed to execute 'toDataURL'

LimeJS 的 lime.fill.Frame 可以讓我們擷取一張圖片中的某一部份,這個功能搭配 lime.animation.KeyframeAnimation 可以很方便的製作某一角色的動畫。不過,不知自何時起,Chrome 在載入本機的圖片時,會出現以下的錯誤訊息:

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.


追了 frame.js 中的程式,錯誤發生在要把原始大圖擷取小塊給 canvas 時的這一段:

var contents = this.ctx.canvas.toDataURL("image/png")

如果同一支程式放到網路上,並不會發生這種情形。這又是基於安全考量的 CORS 政策所造成的,Chrome 擋掉了將「file://」來源的圖片切割給 canvas。

本來試著照網路找到的方式解決,上有人提到設定圖片的 crossOrigin 為 Anonymous 即可過關。來來回回試了很多次,浪費了不少時間,均沒有成功。

一不做,二不休,把圖檔直接轉為用 base64 編碼,再給 lime.fill.Frame 用,比較快啦!

圖片轉 base64 編碼可以利用這個網站:



我把轉好的圖片資料設定給變數,再丟給 lime.fill.Frame 去用,類以底下的內容:

var imageBird1 = 'data:image/png;base64,iVBORw0........';
var imageBird2 = 'data:image/png;base64,iVBORw0........'; 
var birdAni = new lime.animation.KeyframeAnimation().setDelay(.15).setLooping(true);
birdAni.addFrame( new lime.fill.Frame(imageBird1,0, 0,173,89));
birdAni.addFrame( new lime.fill.Frame(imageBird2,0, 0,173,89));
bird.runAction(birdAni);

這樣子就可以製作簡單的二格動畫了。

2016年12月10日 星期六

FFmpeg : 影片剪接與加馬賽克

影片的剪輯不一定要使用圖形界面來操作的,如果只是想進行簡單的剪接而已,利用 ffmpeg 這個自由軟體,下指令即可進行剪接,甚至加上特效。

以底下的某化妝品廣告影片為例:



分析原廣告片,在 00:02:28.500 和 00:02:46.001 以後各有 1.5 秒 和 2 秒長的時間會出現商品的名稱,另外在 00:03:13 以後會有全版的廣告。片尾的廣告只要截掉不取即可,不過中間會有兩段要為商品名稱加上馬賽克。

本篇中會使用到兩個工具,都可以在網路中找到:

影片下載

在 YouTube 中的影片,可以片利用 youtube-dl 下載。假設我們將下載回來的 FullHD 的影片儲存為 source.mp4。

切割影片

利用 ffmpeg 將原始影片(本例中的 source.mp4)切割為五分段,並輸出為 s1.mp4、s1.mp4、s1.mp4、s1.mp4、s1.mp4,五個影片檔。指令如下:

ffmpeg -i source.mp4 -ss 00:00:00.00 -t 00:02:28.500 -y -c copy s1.mp4 
ffmpeg -i source.mp4 -ss 00:02:28.501 -t 00:00:01.500  -y -c copy s2.mp4 
ffmpeg -i source.mp4 -ss 00:02:30.001 -t 00:00:16.000  -y -c copy s3.mp4 
ffmpeg -i source.mp4 -ss 00:02:46.001 -t 00:00:02.00 -y -c copy s4.mp4 
ffmpeg -i source.mp4 -ss 00:02:48.001 -t 00:00:25.00 -y -c copy s5.mp4

上述指令中,「-ss」設定了分段影片的開始時間,而「-t」設定了分段影片的長度。

加馬賽克

我們可以利用 ffmpeg 的濾鏡功能來為 s2.mp4 和 s4.mp4 這兩段有 mark 的地方加上馬賽克。

下載回來的影片,解析度是 1920 x 1080 ,而

  •  s2.mp4 中需要加馬賽克的大小假設為 960x540,放置的座標為 (380,270)
  •  s4.mp4 中需要加馬賽克的大小假設為 1160x540,放置的座標為 (380,270)

最後再用原來的檔名覆蓋儲存即可。執行底下的兩行指令:

ffmpeg -i s2.mp4  -filter_complex  "[0:v]crop=960:540:380:270,boxblur=10[fg];  [0:v][fg]overlay=380:270[v]" -map "[v]" -map 0:a -c:a copy -movflags +faststart  -y s2.mp4 
ffmpeg -i s4.mp4  -filter_complex  "[0:v]crop=1160:540:380:270,boxblur=10[fg];  [0:v][fg]overlay=380:270[v]" -map "[v]" -map 0:a -c:a copy -movflags +faststart  -y s4.mp4
上面的濾鏡參數:

  • [0:v] : 指出是針對第一個影片設定。
  • crop=960:540:380:270 在座標 (380, 27) 處取 960x540 大的畫面
  • boxblur : 馬賽克

連接影片

分段影片都處理好了,最後我們利用 ffmpeg 將 s1.mp4、s2.mp4、s3.mp4、s4.mp4、s5.mp4 五個檔案連接起來,並儲存為 new_movie.mp4,執行底下的這行指令:

ffmpeg -i s.mp4 -i out2.mp4  -i out3.mp4  -i out4.mp4  -i out5.mp4 -filter_complex concat=n=5:v=1:a=1 -y new_movie.mp4

concat 參數的部份:

  • n=5 : 有 5 個影片
  • v=1 : 有影片
  • a=1 : 有聲音


透過前面的操作以後,最後輸出的影片裡,看不到商品的名稱了。ffmpeg 實在好強,有空再來研究一下別的玩法。

相關文章



2016年12月6日 星期二

LimeJS : 使用 this 產生 WARNING

在 LimeJS 中使用「build」參數來產生 .js 檔時,常常會出現一堆類似底下的「WARNING」:


WARNING - dangerous use of the global this object ......

WARNING - dangerous use of this in static method ......

追了一下程式碼,這些訊息主要是發生在我自己寫的元件中使用「this」。因為編譯完的程式仍然可以正常執行,該有的效果都有出來,LimeJS 用了幾年了,哈!一直沒理它,不過,追求完美的我,心中仍然有一點芥蒂。

剛剛用關鍵字去搜尋了一下,看到底下這個討論串,頓時豁然開朗:



LimeJS 主要是架構在 Google 的 Closure Compiler 上,而問題就出在我沒照人家的規定,在  constructor function 的前面加上宣告  constructor 的註解,以致在 complie 的時候被認為會出問題而警告,只要 constructor function 的前面至少加上以下的註解 (JSDoc tags) 即可:

/**
 * @constructor
 */

那如果不是 constructor function,可以單獨指出「this」是哪一種物件,例如:

/**
 * @this {lime.Sprite}
 */

至於還可以使用哪些「JSDoc tags」,可參考 Closure Compiler 網站上的說明:


改完,哇!終可以不用看到一堆 WARNING 的結果了。


2016年11月11日 星期五

LimeJS : hitTest

最近寫了一個將物體拖曳到天平秤重的程式,原本的程序是利用 ['mousedown','touchstart'] 來觸發 Drag 事件,不過 LimeJS 預設會在最後將物體移到 DropTarget 上,也就是秤盤的中心點上,這樣的畫面實在很不自然,在不知道要將移動物體位置的程序安插在哪個事件中的情形下,只好放棄使用 drag 的相關事件,改在 ['mouseup','touchend', 'touchcancel'] 時用「hitTest」來判斷是否已將物體拖曳至秤盤上。

查看了 LimeJS 的 node.js 中的「hitTest」,它其實是抓參數的 .screenPosition 值(一般為滑鼠的所在位置),並利用 screenToLocal 轉換為要和要檢查是否碰撞物體同一系統的座標。

這下又產生新問題了,以將物體放到秤盤上來說,一般人的直覺會在滑鼠指標對準物體的中心左右按下滑鼠開始拖曳,然後當物體的邊緣碰到待測試的東西邊緣時可能就放開滑鼠按鍵,這樣一來,滑鼠指標的位置並不會在秤盤上,測試兩物體是否「碰撞」,理所當然就傳回 false。

為了解決上述的問題,只好修改測試碰撞的座標,改以物體邊緣的座標來測試。

LimeJS 裡, node.js 中的「hitTest」原本應該傳一個 lime.events.Event 型態的 e Event object 來當參數,不過,看 hitTest 的原始碼,它是要抓 e.screenPosition,所以我們只要傳一個物件,且帶有一個名為 screenPosition 的座標變數給它即可(記得先轉為 screen 的座標系統)。

以拖曳 sprite 這個物體為例,具體的程序如下:

var pos =  new Object();
pos.pos = sprite.getPosition();
pos.pos.y += sprite.getSize().height*2/3;
pos.screenPosition = sprite.getParent().localToScreen(pos.pos);

上面把測試的座標往下移 2/3 個 sprite 高度,因為我們起算的座標都是以 sprite 的觀點,而 sprite 是存在於它的 parent 中,所以我們用 sprite.getParent().localToScreen 來轉換座標,算出它的 screenPosition。

處理完座標後,我們就可以利用底下的語法來測試 targetObject 和 sprite 是否碰撞了

 targetObject.hitTest(pos) 


LimeJS 除了 localToScreen ,還有 localToNode 和 localToParent 可以用來轉換座標,滿值得研究的。


2016年10月31日 星期一

Tools : youtube-dl 下載影片的利器 part 4

關於 youtube-dl 這個強大的工具,之前寫過三篇介紹(詳見文末的相關文章),再追加一篇,如何連字幕一起下載。

youtube-dl 關於字幕的參數有:

  • --write-sub
  • --write-auto-sub
  • --all-subs
  • --list-subs
  • --sub-format FORMAT
  • --sub-lang LANGS
  • --embed-subs
  • --convert-subs FORMAT

以 YouTube 的影片來說,它的字幕 format 目前提供 vtt 和 ttml 兩種格式,我們可以利用底下指令來查詢:

youtube-dl --list-subs 影片網址

不過,我常用的影片播放程式 VLC 好像沒有支援 vtt 格式,沒關係,youtube-dl 的好朋友 ffmpeg 可以幫我們轉換為 VLC 支援的 srt 格式字幕檔。

所以,如果想在 YouTube 影片下載以後,順便:
  • 下載字幕檔。(使用 --write-sub --all-subs 參數)
  • 轉為 srt  格式的字幕檔。(使用 --convert-subs srt 參數)
  • 將字幕嵌入影片檔中。(使用 --embed-subs 參數)
就需要先下載底下兩支程式:
並將兩支程式放在同一個目錄中來搭配使用。

最後執行以下指令:

youtube-dl --write-sub  --all-subs --embed-subs --sub-format srt  影片網址

即可下載帶有字幕的 YouTube 影片。

什麼!下指令很麻煩!

好吧!我將之前的「Youtube-影片下載.vbs」改了一下,將下載所有字幕的參數加進去了,只要將這個有下載字幕的版本和 youtube-dl 及 ffmpeg 放在一起,就能變成有字幕的 YouTube mp4 影片囉!

檔案下載



相關文章



2016年10月30日 星期日

Mac : 依日期分目錄歸檔的 shell script

幫同事救行動碟中的資料,由於救回的檔案幾乎只剩一堆編號,原來的檔名都不見了,加上資料量大,於是想順便幫忙把照片檔案按日期分別置入不同的資料夾中。找到在 Ask MetaFilter 中的這篇文章:


裡面是利用 shell script 去呼叫 Mac OS X 中的底下幾個指令來達成按日期歸檔的:

  • 「ls -1」:列出目錄中所有的檔案檔名。
  • 「mdls」:列出檔案的 metadata contents。
  • 「grep CreationDate」:只顯示帶有「CreationDate」的那行資料。
  • 「awk '{print $3}'」:以空白當分隔符號,取出第三個欄位的資料(年月日)。
  • 「export date=」:將找出的日期設為「date」的環境變數

以此來判斷日期的目錄是否存在,已存在就執行「cp」的指令複製檔案,不存在則先利用「mkdir」指令來建立目錄後,再執行檔案複製。

因為我已經將救回的檔案備份到另一顆隨身碟中了,所以在備份目錄中的操作,將原網頁中的指令改用「mv」指令,也就是用搬移來取代複製。

另外,此次救援的主要對象是照片和影片檔案,所以在列出檔案清單的「ls」指令後面加上了可能的副檔名「*.jpg *.nef *.mp4 *.mpg *.avi *.mov」來過濾,只搬移那些副檔名的檔案,其它的都不處理。

底下是依日期分目錄歸檔的 shell script :

#!/bin/bash
for image in `ls  -1 *.jpg *.nef *.mp4 *.mpg *.avi *.mov`; do export date=`mdls $image | grep CreationDate | awk '{print $3}'`;
if [ -d ./$date/ ]
then
mv $image ./$date/
else
mkdir ./$date/ && mv $image ./$date/
fi; done
exit

參考文章:

 
© 2009. Design by Pocket