【Wails】一起來做個桌面程式小工具吧…

以前記得在Windows的bat小程式,可以用拉檔案到圖示上去執行,不用輸入路徑,真的很方便,但在macOS上就是不行,所以想自己做一個,不過當時都是用Electron這個多平台框架去做的,又大又吃資源,做一個小小的工具就上百MB,所以就沒有學下去了;不過到了今日,有許許多多的多平台框架出現,加上對Golang有一點點基本的了解,所以就選Wails了,而且它是以作業系統裡的WebView去實現的,雖然有可能長相會有一點點差別,但包裝起來的檔案比Electron小太多了啊… 說到多平台框架,最流行的就是Flutter了,本來它用的Dart語言,就是要用來取代JavaScript,結果因為手機的流行,加上原生支援,就把它帶起來了,不過呢,個人覺得開發還是網頁歸網頁,手機歸手機才是… 其實還有一個叫Tauri的工具,也是滿流行的,新版的也支援手機的開發,但它是以WebView為基礎的,所以在支援上就沒有Flutter來的好了… 以WebView為主的多平台框架還有React Native / Dioxus / PyWebView / WebView-Bun / WebView-Nodejs / WebView_Java / Lua-WebView / Kivy / NW.js,另外也有像SkipQt應該也算是一類吧…

我們要做一個簡單版的HLS檔案產生器

作業環境

項目 版本
macOS Sequoia 15.3.2
Xcode 16.2
FFmpeg 7.1.1
Go 1.24
Nodejs 22.14 LTS
Wails 2.10.1

簡介

  • Wails 是一個可讓您使用 Go 和 Web 技術編寫桌面應用的項目
  • Windows、macOS 和 linux 支援
  • 內建 Svelte、React 、Preact 、Vue、Lit 和 Vanilla JS 的範本
  • 從 JavaScript 輕鬆呼叫 Go 方法
  • 自動將 Go 結構體轉換為 TypeScript 模組

安裝

  • gonodejs 的安裝大家可以參考一下之前的文章…
  • wails的安裝就執行以下的指令,就可以安裝最新的版本了…
go install github.com/wailsapp/wails/v2/cmd/wails@latest

  • 安裝完成後,也可以請醫生檢查一下…
wails doctor

建立新專案

  • 可以使用wails命令建立新專案…
  • 其實wails = 網頁前端 + Golang後端,而前端框架可以選擇Svelte / React / Preact / Vue / Lit / Vanilla JS
  • 這些前端框架都有TypeScript的版本可供選擇…
wails init -n <專案名稱> -t <前端框架名稱>
wails init -n <專案名稱> -t <前端框架名稱>-ts
  • 我們建立一個名叫「new_project」的專案,使用「vanilla」前端框架…
  • 最後讓APP跑起來,雖然是說APP,但其實它是網頁啦…
wails init -n new_project -t vanilla
cd new_project
wails dev

打包成執行檔

  • 在這裡可以使用wails build -platform來指定要生成的平台版本
  • CPU類型 - amd64 / arm64
  • 平台類型 - windows / darwin / linux
  • 我們就來打包個macOS的APP試試看…
  • 打包完成後,就會出現在bin資料夾下,是不是很簡單啊?
wails build -platform <平台類型>/<CPU類型>
wails build -platform darwin/arm64

Debug

  • 因為它本身其實是網頁,所以Debug也可以在瀏覽器上執行…
wails dev
wails dev -browser

HLS產生器

  • 接下來我們利用系統安裝好的ffmpeg指令,來做一個簡易的HLS檔案產生器…
  • 使用簡單Svelte框架來建立…
wails init -n wails_ffmpeg -t svelte

設定主畫面大小

  • 在main.go的地方,就是程式的進入點
  • 將標題 / 尺寸…等相關的設定先設定好…

設定畫面長相

  • 這邊就不細說了,主要還是網頁方面的設定…
  • 程式碼主要都在front/src之下…

HLS轉換程式

  • 最重要的地方就是在這裡,按下去怎麼去啟動系統上的ffmpeg…
  • 在app.go的地方寫程式碼,利用go的exec函式,去呼叫OS上的ffmpeg指令…
func convertToHLS(fullPath string) error {

	dirPath := filepath.Dir(fullPath)
	hlsDir := dirPath + "/hls"

	println(hlsDir)

	cmd := exec.Command("mkdir",
		"-p", hlsDir,
	)
	cmd.Run()

	cmd = exec.Command("ffmpeg",
		"-i", fullPath,
		"-profile:v", "baseline",
		"-level", "3.0",
		"-start_number", "0",
		"-hls_time", "10",
		"-s", "640x480",
		"-hls_list_size", "0",
		"-f", "hls",
		hlsDir+"/playlist.m3u8")

	err := cmd.Run()

	if err != nil {
		return err
	}

	return nil
}

測試

  • 最後我們找部影片來試試看吧…
http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4

範例程式碼下載

後記

  • 說實在的,這支程式是照著它一開始的Code改過來的,雖然寫得不好,但還是可以用的啦…
  • 大家現在知道m3u8的影片是怎麼來的吧…