多媒體程式開發



多媒體程式開發

多媒體程式開發是指整合文字、圖像、音訊、視訊及動畫,透過程式語言實作互動功能的技術領域。其開發重點在於硬體加速、編碼效率以及使用者體驗的流暢度。


核心開發組件

主流開發工具與語言

開發領域 常用語言 技術框架/工具
網頁多媒體 JavaScript / TypeScript HTML5 Canvas, WebGL, Three.js
行動應用/遊戲 C++ / C# / Swift Unity, Unreal Engine, Metal
後端影音處理 Python / Go / C++ FFmpeg, OpenCV, GStreamer

常見開發流程

  1. 需求分析:確定媒體類型(如串流媒體、互動遊戲、教育軟體)。
  2. 資源準備:素材採集與格式轉檔(優化檔案大小與解析度)。
  3. 程式撰寫:實作播放邏輯、濾鏡效果或互動演算法。
  4. 效能調優:進行記憶體管理與多執行緒優化,確保高幀率運行。
  5. 部署與測試:跨平台相容性測試,確保在不同螢幕尺寸與硬體規格下皆能運作。
注意:在開發涉及大量運算的多媒體程式時,應優先考量硬體解碼(Hardware Decoding)以降低 CPU 負載。


DirectX

DirectX 是由微軟開發的一系列應用程式介面(API),旨在讓軟體(特別是遊戲)能直接與顯示卡、音效卡等硬體溝通。它是 Windows 平台與 Xbox 主機多媒體開發的核心支柱。


主要 API 組件

DirectX 版本演進比較

版本 重要特性 適用環境
DirectX 11 引入曲面細分 (Tessellation) 與多執行緒渲染,穩定性高。 Windows 7 及以上版本
DirectX 12 底層 API(Low-level),大幅降低 CPU 開銷,支援顯卡多核心調度。 Windows 10 / 11
DirectX 12 Ultimate 整合光線追蹤 (Ray Tracing)、網格著色器 (Mesh Shaders) 等次世代技術。 高階 GPU 與 Xbox Series X/S

開發優勢

  1. 硬體抽象化:開發者不需針對不同品牌的顯卡撰寫特定程式碼。
  2. 高效能:DirectX 12 讓開發者能更精細地管理 GPU 資源,減少系統延遲。
  3. 生態系完整:與 Visual Studio 及微軟開發工具鏈緊密結合,並有豐富的調試工具(如 PIX)。
注意:在現代遊戲開發中,開發者通常透過 Unity 或 Unreal Engine 等引擎呼叫 DirectX,而非直接撰寫底層指令,以提高開發效率。


Media Foundation

Media Foundation (MF) 是微軟在 Windows Vista 之後推出的多媒體框架,旨在取代舊有的 DirectShow。它採用全新的管線設計,專為高解析度視訊、數位版權管理 (DRM) 以及更高效的硬體加速而優化,是現代 Windows 應用程式處理影音的核心技術。


核心架構組件

Media Foundation 將多媒體處理過程拆解為三個主要層級,這種設計提供了極高的控制彈性:

技術優勢比較

特性 Media Foundation DirectShow (舊版)
高解析度支援 原生優化 4K、8K 與 HDR 內容。 擴充性有限,處理超高解析度較吃力。
硬體加速 深度整合 DXVA 2.0,效率極高。 依賴特定篩選器實作,效能不一。
內容保護 內建 PMP (Protected Media Path) 支援 DRM。 缺乏統一的版權保護機制。
執行緒模型 採用非同步拓撲,減少 UI 凍結。 同步執行模型,易導致介面卡頓。

常用開發介面

  1. Source Reader: 一種簡化的 API,適合只需要從檔案或相機獲取解碼後影格的開發者。
  2. Sink Writer: 用於將影音資料編碼並寫入特定格式檔案的快速工具。
  3. Media Session: 完整的管線控制器,提供對播放、暫停、跳轉等動作的全方位掌控。
注意:雖然 Media Foundation 效能優異,但其 API 設計相對複雜且嚴謹,建議開發者搭配微軟提供的 MFTrace 工具進行除錯,以追蹤媒體管線中的事件流。


DirectShow

DirectShow 是基於元件物件模型 (COM) 的多媒體框架,主要用於 Windows 平台上的影音截取與回放。雖然微軟後來推出了 Media Foundation 作為繼任者,但 DirectShow 因其強大的相容性與靈活性,至今仍在工業相機、醫療影像及傳統影音軟體中廣泛使用。


篩選器圖形模型

DirectShow 的核心概念是篩選器圖形 (Filter Graph),透過將不同的篩選器連接成鏈結來處理多媒體資料:

核心開發功能

功能分類 說明
媒體播放 支援多種容器格式(如 AVI, WMV, MP4)與編解碼器的整合。
影像截取 提供與 WDM (Windows Driver Model) 設備溝通的標準介面,適用於 USB 相機。
硬體加速 可透過 Video Mixing Renderer (VMR) 或 EVR 利用顯示卡進行硬體加速渲染。
格式轉換 支援即時影音流的重新取樣、裁切以及色彩空間轉換(如 YUV 轉 RGB)。

開發優點與挑戰

  1. 高度模組化: 開開發者可以撰寫自定義的篩選器並插入現有的圖形鏈結中。
  2. 自動化連線: 擁有智慧連線 (Intelligent Connect) 機制,能自動尋找並組合中間所需的篩選器。
  3. 學習曲線: 由於深度依賴 COM 介面,對於不熟悉 COM 指標與記憶體管理的開發者來說較為複雜。
注意:在進行現代化開發時,若不需要支援過舊的系統,微軟建議優先考慮使用 Media Foundation,它在處理高解析度內容與數位版權管理 (DRM) 上更具優勢。


Vulkan

Vulkan 是由 Khronos Group 開發的次世代跨平台圖形與運算 API。與 OpenGL 不同,Vulkan 屬於底層(Low-level)API,旨在提供更直接的硬體控制權,極大化減少驅動程式的額外負擔(Overhead),並提升多核心處理器的利用率。


核心設計特點

Vulkan 的設計邏輯要求開發者承擔更多管理責任,以換取極致的效能表現:

Vulkan 與 OpenGL 之差異

特性 Vulkan OpenGL
驅動程式負擔 極低,大部分邏輯由開發者實作。 較高,驅動程式負責大量背景管理。
多執行緒支援 原生支援並行任務分配。 主要依賴單一執行緒。
開發複雜度 極高,程式碼量通常是 OpenGL 的數倍。 中等,對初學者較為友好。
硬體利用率 高,可精準控制 GPU 運算與記憶體。 中,受限於 API 的抽象層級。

關鍵開發組件

  1. Instance & Physical Device: 初始化 Vulkan 並枚舉系統中的顯示卡硬體。
  2. Logical Device & Queues: 從實體設備建立邏輯連接,並獲取處理圖形、運算或傳輸任務的佇列。
  3. Pipeline State Objects (PSO): 將渲染狀態(如混合模式、深度測試)預先封裝,避免在繪圖時動態變更狀態導致效能掉幀。
  4. Render Pass: 明確定義渲染目標與操作步驟,有利於行動端 GPU 的磁貼渲染(Tile-based rendering)優化。
注意:由於 Vulkan 的開發門檻極高,通常建議用於需要極致效能的 3D 遊戲引擎核心(如 id Tech 7)或需要跨平台高效能運算的科學模擬程式。


機器視覺程式開發

OpenCV

1. OpenCV 是什麼?

OpenCV (Open Source Computer Vision Library) 是一個開源的計算機視覺與機器學習軟件庫,用於即時影像處理與分析。

2. 支援的功能

3. 支援的平台

4. 使用範例

# 讀取影像並顯示
import cv2
image = cv2.imread("image.jpg")
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

5. 資源與文件



cv::imread

1. 基本語法

在 OpenCV 中,讀取影像最核心的函式是 cv::imread。它會將影像檔案載入為 cv::Mat 矩陣格式。


#include <opencv2/opencv.hpp>

// 語法原型
cv::Mat img = cv::imread(const std::string& filename, int flags = cv::IMREAD_COLOR);

常用的標籤 (Flags):


2. 異常檢查與處理機制

重要觀念:cv::imread 失敗時並不會拋出 C++ 異常,因此傳統的 try-catch 對其無效。當讀取失敗(如路徑錯誤、格式不支援或權限不足)時,它會返回一個空的 cv::Mat 物件。

正確的處理流程應使用 empty() 成員函式進行檢查:


#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    std::string path = "data/image.jpg";
    cv::Mat img = cv::imread(path);

    // 必須檢查影像是否成功載入
    if (img.empty()) {
        std::cerr << "錯誤:無法讀取影像檔案!" << std::endl;
        std::cerr << "請確認路徑是否正確:" << path << std::endl;
        return -1;
    }

    // 讀取成功後才執行操作
    std::cout << "影像寬度: " << img.cols << " 高度: " << img.rows << std::endl;
    return 0;
}

3. 常見失敗原因分析

如果 img.empty() 為真,通常是由以下原因導致:

原因 說明與對策
檔案路徑錯誤 最常見原因。請檢查相對路徑是否相對於執行檔目錄,或使用絕對路徑。
不支援的副檔名 OpenCV 需對應解碼器(如 libjpeg, libpng)。若編譯 OpenCV 時未加入支援,則無法讀取。
中文路徑問題 在 Windows 環境下,舊版或特定編譯環境的 cv::imread 對中文路徑支援不佳。
權限不足 執行程式的使用者沒有讀取該檔案的作業系統權限。

4. 進階解決方案:中文路徑讀取

若遇到 Windows 中文路徑導致讀取失敗,建議先將檔案讀入記憶體 Buffer,再透過 cv::imdecode 進行解碼:


#include <fstream>
#include <vector>

cv::Mat imread_unicode(std::string path) {
    std::ifstream fs(path, std::ios::binary | std::ios::ate);
    if (!fs.is_open()) return cv::Mat();

    std::streamsize size = fs.tellg();
    fs.seekg(0, std::ios::beg);

    std::vector<char> buffer(size);
    if (fs.read(buffer.data(), size)) {
        return cv::imdecode(cv::Mat(buffer), cv::IMREAD_COLOR);
    }
    return cv::Mat();
}


振盪點群分群

當點群(如螺絲邊緣或正弦波)的順序混亂時,必須先將其投影至擬合直線的方向上進行排序,隨後才能根據點相對於直線的正負偏移量(Signed Distance)進行正確的分群。以下是整合 OpenCV 與標準 C++ 的實作方案。


座標點定義與距離排序

首先實作你要求的指定點距離排序功能。這可用於定位起始點或特定特徵點。


#include <vector>
#include <array>
#include <algorithm>
#include <opencv2/opencv.hpp>

using Point2D = std::array<float, 2>;
using Points = std::vector<Point2D>;

namespace GeometryPointsUtil {
    bool FindSortedPointsByDistOfPoint(Points& retPoints, const Points& allPoints, const Point2D& aPoint) {
        if (allPoints.empty()) return false;

        retPoints = allPoints;
        std::sort(retPoints.begin(), retPoints.end(), [&aPoint](const Point2D& p1, const Point2D& p2) {
            float dx1 = p1[0] - aPoint[0];
            float dy1 = p1[1] - aPoint[1];
            float dx2 = p2[0] - aPoint[0];
            float dy2 = p2[1] - aPoint[1];
            // 使用平方和比較以避免 sqrt 運算開銷
            return (dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * dy2);
        });
        return true;
    }
}

亂序點群的沿線分群演算法

針對震盪線條,此函數會自動擬合直線、投影排序,並根據直線兩側進行切分。


std::vector<Points> splitOscillatingPoints(const Points& allPoints) {
    if (allPoints.size() < 2) return {allPoints};

    // 1. 直線擬合
    std::vector<cv::Point2f> cvPts;
    for (const auto& p : allPoints) cvPts.push_back({p[0], p[1]});
    
    cv::Vec4f line; // (vx, vy, x0, y0)
    cv::fitLine(cvPts, line, cv::DIST_L2, 0, 0.01, 0.01);
    float vx = line[0], vy = line[1], x0 = line[2], y0 = line[3];

    // 2. 投影排序:確保點是沿著直線方向排列
    struct ProjectedPoint {
        Point2D original;
        float t; // 投影長度
        float side; // 到直線的代數距離
    };

    std::vector<ProjectedPoint> projected;
    float nx = -vy; // 法向量 x
    float ny = vx;  // 法向量 y

    for (const auto& p : allPoints) {
        float dx = p[0] - x0;
        float dy = p[1] - y0;
        float t = dx * vx + dy * vy;    // 投影到直線上的位移
        float s = dx * nx + dy * ny;    // 垂直於直線的距離(含正負號)
        projected.push_back({p, t, s});
    }

    std::sort(projected.begin(), projected.end(), [](const ProjectedPoint& a, const ProjectedPoint& b) {
        return a.t < b.t;
    });

    // 3. 根據正負號跳變進行分群
    std::vector<Points> segments;
    if (projected.empty()) return segments;

    Points currentGroup;
    bool lastSide = (projected[0].side >= 0);

    for (const auto& item : projected) {
        bool currentSide = (item.side >= 0);

        if (currentSide != lastSide && !currentGroup.empty()) {
            segments.push_back(currentGroup);
            currentGroup.clear();
        }
        
        currentGroup.push_back(item.original);
        lastSide = currentSide;
    }

    if (!currentGroup.empty()) segments.push_back(currentGroup);
    return segments;
}

實作要點說明



Halcon

特點

Halcon 是由 MVTec 公司開發的一款強大的工業視覺軟體,專為影像處理和機器視覺應用而設計。

功能

應用領域

資源



影片編輯程式開發

常見功能

常用工具與Library

應用範例



開源影片編輯軟體

1. Shotcut

Shotcut 是一款免費且開源的影片編輯軟體,支援多種格式且具有許多強大的編輯工具。其特色包括:

適用平台:Windows、Mac、Linux

2. OpenShot

OpenShot 是一款易於上手的開源影片編輯工具,功能強大且支持多種格式。其主要特點包括:

適用平台:Windows、Mac、Linux

3. Blender

Blender 是一款知名的開源 3D 建模和動畫軟體,內建功能強大的影片編輯器,適合進行影片剪輯和特效製作。其功能包括:

適用平台:Windows、Mac、Linux

4. Kdenlive

Kdenlive 是 Linux 上廣泛使用的開源影片編輯軟體,也支援 Windows。其主要功能包括:

適用平台:Windows、Mac、Linux

5. Lightworks

Lightworks 提供免費和付費版本,免費版本具備基本編輯功能。其特色包括:

適用平台:Windows、Mac、Linux

. Avidemux
. Cinelerra
. LiVES
. Losslesscut
. Natron
. Pitivi

以上這些開源影片編輯軟體提供了強大的功能,適合不同層次的影片編輯需求,從簡單的家庭影片剪輯到專業級的影片製作都可以滿足。

Google 搜尋量排名

軟體名稱 大約搜尋量
OpenShot 110,000
Kdenlive 90,500
Shotcut 49,500
Avidemux 18,100
Losslesscut 14,800
Blender VSE 10,000
Natron 6,600
Cinelerra 5,400
Pitivi 3,600
LiVES 1,600


影片編輯好用的程式庫

FFmpeg

MoviePy(Python)

OpenCV(C++/Python)

GStreamer

AVFoundation(macOS/iOS)

Microsoft Media Foundation(Windows)

Kapwing API / Shotstack / Cloudinary

Adobe Premiere Pro API(Adobe UXP)



OpenShot

專案簡介

OpenShot 是一款免費且開源的影片編輯器,專案名稱為 OpenShot/openshot-qt,主要基於 PythonQt 開發。該專案旨在提供一個易於使用且功能豐富的影片編輯工具,適合不同水平的使用者。

功能特色

技術架構

OpenShot 使用 PyQt 作為圖形用戶界面,並結合 libopenshot (C++ 實現) 來處理影片編輯的核心邏輯。此外,OpenShot 還利用了 FFmpeg 來支援多種格式的解碼與編碼。

使用情境

OpenShot 適用於需要簡單操作、但功能強大的影片編輯需求的用戶。無論是業餘影片創作者還是教育用途,OpenShot 都提供了靈活的工具和插件,便於進行剪輯和創作。

社群和貢獻

OpenShot 專案擁有活躍的開源社群,使用者和開發者可以透過 GitHub 貢獻程式碼、報告問題或提交新功能建議。歡迎所有人參與,以協助提升 OpenShot 的功能與穩定性。

如何取得 OpenShot

使用者可以透過 GitHub 頁面下載源碼,或從 OpenShot 官方網站下載可執行檔。詳細安裝指引和說明文件也可在 GitHub 上找到。



Python Kdenlive 自動化

Kdenlive 專案檔案 (KDENLIVE) 運作原理

Kdenlive 的專案檔本質上是 XML 格式的純文字檔案。要實現「自動開啟並匯入」,最穩定且高效的方法不是模擬滑鼠點擊,而是使用 Python 直接生成或修改該 XML 檔案,隨後再呼叫 Kdenlive 程式開啟它。這種方式可以精準地指定語音、字幕(SRT)與影片在時間軸上的位置。

自動化匯入腳本實作

此腳本示範如何建立一個基礎的 Kdenlive 專案 XML 結構,並將您指定的資源路徑寫入其中。

import os
import subprocess

def create_kdenlive_project(project_path, video_path, audio_path, srt_path):
    """
    建立一個基礎的 Kdenlive XML 專案檔並匯入素材
    """
    # 取得檔案絕對路徑以確保 Kdenlive 能正確讀取
    video_abs = os.path.abspath(video_path)
    audio_abs = os.path.abspath(audio_path)
    srt_abs = os.path.abspath(srt_path)

    # 基礎 Kdenlive MLT 結構 (簡化版)
    kdenlive_xml = f"""<?xml version="1.0" encoding="UTF-8"?>
<mlt version="7.24.0" title="Auto Generated Project">
  <producer id="video_main" resource="{video_abs}"/>
  <producer id="audio_main" resource="{audio_abs}"/>
  <producer id="subtitle_main" resource="{srt_abs}"/>
  
  <playlist id="main_bin">
    <entry producer="video_main"/>
    <entry producer="audio_main"/>
    <entry producer="subtitle_main"/>
  </playlist>

  <tractor id="main_timeline">
    <multitrack>
      <track name="Video Track">
        <entry producer="video_main" in="0" out="1000"/>
      </track>
      <track name="Audio Track">
        <entry producer="audio_main" in="0" out="1000"/>
      </track>
    </multitrack>
  </tractor>
</mlt>
"""

    with open(project_path, "w", encoding="utf-8") as f:
        f.write(kdenlive_xml)
    print(f"專案檔已生成:{project_path}")

def open_with_kdenlive(project_path, kdenlive_exe_path):
    """
    啟動 Kdenlive 並載入生成的專案
    """
    try:
        # 使用 subprocess 開啟程式並帶入檔案參數
        subprocess.Popen([kdenlive_exe_path, project_path])
        print("正在啟動 Kdenlive...")
    except Exception as e:
        print(f"啟動失敗:{e}")

if __name__ == "__main__":
    # 設定檔案路徑
    MY_VIDEO = "input_video.mp4"
    MY_AUDIO = "output_voice.wav"
    MY_SRT = "output_subtitle.srt"
    SAVE_PROJECT = "auto_project.kdenlive"
    
    # Kdenlive 執行檔路徑 (Windows 範例,Linux 通常直接用 'kdenlive')
    KDENLIVE_PATH = r"C:\Program Files\kdenlive\bin\kdenlive.exe"

    # 1. 生成專案檔
    create_kdenlive_project(SAVE_PROJECT, MY_VIDEO, MY_AUDIO, MY_SRT)
    
    # 2. 開啟 Kdenlive
    open_with_kdenlive(SAVE_PROJECT, KDENLIVE_PATH)

進階自動化建議



MLT 多媒體框架

MLT (Media Lovin' Toolkit) 核心架構

MLT 是一個開源的多媒體框架,也是 Kdenlive、Shotcut 等剪輯軟體的底層引擎。它採用非線性剪輯(NLE)設計,將影片、音訊、濾鏡與轉場定義為 XML 結構(稱為 MLT XML),並透過高效的管線進行即時預覽或渲染。

MLT 的組成要素

使用 Python 操作 MLT XML 範例

與其在 Kdenlive 手動操作,你可以利用 Python 生成 MLT 腳本,實現自動化批量剪輯。

import subprocess

# 定義一個簡易的 MLT XML 結構
# 這段 XML 定義了兩段素材的先後播放順序
mlt_xml_content = """<mlt>
  <producer id="clip1" resource="video_part1.mp4" />
  <producer id="clip2" resource="video_part2.mp4" />
  <playlist id="main_track">
    <entry producer="clip1" in="0" out="150" />
    <entry producer="clip2" in="0" out="300" />
  </playlist>
</mlt>
"""

# 將內容寫入檔案
with open("auto_edit.mlt", "w", encoding="utf-8") as f:
    f.write(mlt_xml_content)

def render_video(mlt_file, output_file):
    """
    使用 melt 命令行工具直接渲染影片 (無需開啟 GUI)
    """
    # melt 是 MLT 的命令行介面工具
    command = [
        "melt", 
        mlt_file, 
        "-consumer", f"avformat:{output_file}", 
        "acodec=aac", "vcodec=libx264", "preset=fast"
    ]
    
    try:
        print(f"開始背景渲染:{output_file}...")
        subprocess.run(command, check=True)
        print("渲染完成!")
    except FileNotFoundError:
        print("錯誤:找不到 melt 執行檔,請確認是否安裝 MLT 框架。")

if __name__ == "__main__":
    # 執行渲染
    render_video("auto_edit.mlt", "final_result.mp4")

為何選擇 MLT 進行自動化?



Python 剪映自動化

此腳本利用影像辨識定位 UI 元素。在執行前,請先擷取剪映介面中「圖文成片」與「生成影片」按鈕的小圖示,分別儲存為 btn_start.pngbtn_generate.png 存放在程式碼同目錄下。


準備工作

請先安裝必要的 Python 函式庫:

pip install pyautogui pyperclip opencv-python

自動化程式碼範例


import os
import time
import pyautogui
import pyperclip

# 設定參數
JIANYING_PATH = r"C:\Users\YourName\AppData\Local\JianyingPro\Apps\JianyingPro.exe" # 請更換為你的實際路徑
SCRIPT_FILE = "my_script.txt"  # 預先準備好的文稿檔
CONFIDENCE_LEVEL = 0.8         # 影像辨識準確度 (0-1)

def run_automation():
    # 1. 讀取文稿內容
    if not os.path.exists(SCRIPT_FILE):
        print("錯誤:找不到文稿檔案")
        return
    with open(SCRIPT_FILE, "r", encoding="utf-8") as f:
        content = f.read()

    # 2. 開啟剪映
    print("正在啟動剪映...")
    os.startfile(JIANYING_PATH)
    time.sleep(8)  # 等待軟體完全載入

    try:
        # 3. 定位並點擊「圖文成片」按鈕
        start_btn = pyautogui.locateCenterOnScreen('btn_start.png', confidence=CONFIDENCE_LEVEL)
        if start_btn:
            pyautogui.click(start_btn)
            print("已進入圖文成片介面")
            time.sleep(2)
        else:
            print("無法定位『圖文成片』按鈕")
            return

        # 4. 處理文稿輸入
        pyperclip.copy(content)  # 將文稿複製到剪貼簿
        pyautogui.click(x=pyautogui.size().width//2, y=pyautogui.size().height//2) # 點擊視窗中心確保聚焦
        pyautogui.hotkey('ctrl', 'v')
        print("文稿已貼上")
        time.sleep(1)

        # 5. 定位並點擊「生成影片」
        gen_btn = pyautogui.locateCenterOnScreen('btn_generate.png', confidence=CONFIDENCE_LEVEL)
        if gen_btn:
            pyautogui.click(gen_btn)
            print("正在生成專案...")
        else:
            print("無法定位『生成影片』按鈕")

    except Exception as e:
        print(f"發生錯誤: {e}")

if __name__ == "__main__":
    run_automation()

實作關鍵細節

步驟 說明
影像擷取 擷取圖片時,盡量只擷取按鈕中央的文字或圖示,避免包含過多背景色,以增加不同佈景主題下的相容性。
Time Sleep 自動化中最常失敗的原因是「軟體還沒反應,程式就點了」。請根據電腦效能調整 time.sleep 的數值。
Fail-Safe PyAutoGUI 內建保護機制:將滑鼠快速移至螢幕「左上角」可立即中止程式運行。

優化建議

  1. 解析度適配: 如果換了電腦執行,必須重新擷取 .png 圖示,因為螢幕解析度或縮放率(DPI)改變會導致辨識失敗。
  2. 視窗置頂: 建議在點擊前使用 pygetwindow 函式庫強制將剪映視窗設為前台活動視窗。
  3. 多重確認: 可以使用迴圈檢查按鈕是否存在,直到按鈕出現再執行點擊,而非使用固定的等待時間。
注意:頻繁的 UI 自動化可能會因為軟體更新(介面位置改變)而失效。若需長期穩定運行,研究「路徑二:修改 JSON 草稿」會是更健壯的方案。


FFmpeg

簡介

常見功能

優點

使用方式

官網與下載



FFmpeg 自動部署

在多媒體開發中,確保執行環境具備 FFmpeg 是基本需求。透過 Python 的 subprocess 模組與 urllib,我們可以實作自動化的環境配置流程。


核心邏輯流程

程式碼主要分為兩個階段:偵測系統路徑與遠端下載解壓縮。

Python 實作範例


import os
import shutil
import platform
import urllib.request
import zipfile

def ensure_ffmpeg():
    # 1. 檢查系統 PATH 是否已有 ffmpeg
    if shutil.which("ffmpeg"):
        print("FFmpeg 已存在於系統路徑中。")
        return True

    print("未偵測到 FFmpeg,準備開始下載...")
    
    # 2. 根據作業系統設定下載資訊 (以 Windows 為例)
    if platform.system() == "Windows":
        url = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip"
        target_zip = "ffmpeg.zip"
        extract_dir = "ffmpeg_bin"
        
        # 下載檔案
        urllib.request.urlretrieve(url, target_zip)
        
        # 解壓縮
        with zipfile.ZipFile(target_zip, 'r') as zip_ref:
            zip_ref.extractall(extract_dir)
            
        # 尋找解壓後的 bin 目錄並加入環境變數
        # 實際路徑需視壓縮包結構而定
        ffmpeg_path = os.path.abspath(os.path.join(extract_dir, "ffmpeg-release-essentials", "bin"))
        os.environ["PATH"] += os.pathsep + ffmpeg_path
        
        print(f"FFmpeg 已部署至: {ffmpeg_path}")
        return True
    else:
        print("目前範例僅支援 Windows 自動下載,其餘系統請手動安裝。")
        return False

# 執行檢查
ensure_ffmpeg()

開發注意事項

項目 說明
權限問題 在 Linux 或 macOS 下,下載後的二進位檔可能需要透過 os.chmod(path, 0o755) 賦予執行權限。
版本鎖定 建議從可靠的來源(如 Gyan.dev 或 BtbN)下載,並確認版本與你的程式碼相容。
網路超時 FFmpeg 體積較大,下載時建議加入 try-except 處理網路中斷,或使用 requests 庫顯示進度條。

路徑管理建議

  1. 優先順序:程式應先尋找用戶自定義路徑,再尋找系統 PATH,最後才執行自動下載。
  2. 持久化:自動下載的 FFmpeg 建議放在應用程式的 AppData 或專案根目錄,避免重複下載。
  3. 靜態版本:對於發布的應用程式,直接隨附一個靜態編譯(Static Build)的 FFmpeg 執行檔通常比動態下載更穩定。
注意:在生產環境中,頻繁地下載大型二進位檔可能會影響使用者體驗。建議在第一次啟動時提示用戶,或在安裝包中預載。


Python 螢幕錄影

在 Python 中進行螢幕錄影,最常見且穩定的做法是結合 PyAutoGUI(用於擷取畫面)、OpenCV(用於編碼與儲存影片)以及 NumPy(用於處理影像數據)。


1. 準備工作

首先需要安裝必要的套件。打開終端機並執行以下指令:

pip install opencv-python pyautogui numpy

2. 核心實作範例

下方程式碼會擷取全螢幕畫面,並將其儲存為 output.mp4 檔案。按下鍵盤上的 q 鍵即可停止錄影。

import cv2
import pyautogui
import numpy as np

# 取得螢幕解析度
SCREEN_SIZE = tuple(pyautogui.size())

# 定義影片編碼格式 (FourCC)
fourcc = cv2.VideoWriter_fourcc(*"mp4v")

# 建立 VideoWriter 物件 (檔名, 編碼, 幀率, 解析度)
out = cv2.VideoWriter("output.mp4", fourcc, 20.0, SCREEN_SIZE)

print("錄影中... 按下 'q' 鍵停止。")

try:
    while True:
        # 擷取螢幕畫面
        img = pyautogui.screenshot()
        
        # 轉換為 NumPy 陣列
        frame = np.array(img)
        
        # 將顏色從 RGB 轉換為 BGR (OpenCV 標準格式)
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        
        # 寫入影格到影片檔案
        out.write(frame)
        
        # 顯示錄影預覽 (選用)
        # cv2.imshow("Preview", frame)
        
        # 檢測鍵盤輸入
        if cv2.waitKey(1) == ord("q"):
            break
finally:
    # 釋放資源並關閉視窗
    out.release()
    cv2.destroyAllWindows()
    print("錄影結束,檔案已儲存。")

3. 關鍵組件說明


4. 常見問題與解決方案

問題現象 原因與建議
影片播放速度太快 實際錄製的 FPS 低於設定值。應調低寫入的 FPS,或改用更高效的擷取庫如 mss。
顏色不正常 忘記進行 COLOR_RGB2BGR 轉換。
程式碼執行時卡頓 擷取高解析度螢幕非常耗費 CPU,建議降低螢幕解析度或僅錄製特定區域。


Manim - Python Animation

Manim(Mathematical Animation Engine)是一個用 Python 編寫的動畫庫,特別用來創建數學圖像和動畫。Manim 可以用於生成高品質的動畫,展示數學概念、代碼運行過程,或者任何以圖像和動畫表現的東西。

Manim 的主要功能

如何使用 Manim

Manim 的動畫一般是通過編寫 Python 腳本來完成的,然後生成視頻文件。每個動畫通常包含一個或多個場景 (Scene),而每個場景則由不同的對象 (Mobject) 組成。

基本範例


from manim import *

class MyFirstScene(Scene):
    def construct(self):
        text = Text("Hello, Manim!")  # 創建一個文字對象
        self.play(Write(text))  # 生成動畫
    

安裝 Manim

可以通過 pip 安裝 Manim:

pip install manim


3D 圖形與動畫程式開發

OpenGL

OpenGL (Open Graphics Library) 是一個跨語言、跨平台的應用程式介面 (API),用於渲染 2D 與 3D 向量圖形。它由 Khronos Group 維護,廣泛應用於電腦輔助設計 (CAD)、虛擬實境、科學視覺化以及電子遊戲開發。


繪圖管線流程

OpenGL 採用管線 (Pipeline) 架構,將 3D 數據轉換為螢幕上的像素。現代 OpenGL 核心模式高度依賴著色器 (Shaders):

技術特性與優勢

特性 說明
跨平台相容性 可在 Windows、Linux、macOS (透過轉譯層) 及行動裝置 (OpenGL ES) 上執行。
狀態機模型 OpenGL 運作如同一個巨大的狀態機,開發者設定狀態(如當前顏色、綁定的貼圖)後執行繪圖指令。
GLSL 語言 使用類 C 語言的 OpenGL Shading Language 撰寫 GPU 程式,具備強大的運算能力。
擴展機制 允許硬體廠商在不更新 API 標準的情況下,透過 Extension 引入新的顯示卡功能。

核心模式與立即模式

  1. 立即模式 (Immediate Mode): 早期版本使用 glBegin/glEnd 指令,易於學習但效能極低,現已被廢棄。
  2. 核心模式 (Core Profile): 現代開發標準,強制使用緩衝區物件 (VBO/VAO) 與著色器,能發揮硬體最大效能。
注意:雖然 Vulkan 已被視為 OpenGL 的繼任者,提供更底層的硬體控制,但 OpenGL 因其相對簡單的進入門檻與豐富的文檔,仍是學習圖學程式開發的首選。


ManimGL

簡介

ManimGL 是 Manim 的一個高效變體,用於製作數學動畫,專注於 OpenGL 加速來提高渲染速度。

安裝

使用 pip 安裝:

pip install manimgl

或從 GitHub 獲取最新版本:

git clone https://github.com/ManimCommunity/ManimGL.git
cd ManimGL
pip install -e .

基本使用

使用 ManimGL 渲染一個簡單場景:

from manimlib import *

class HelloManim(Scene):
    def construct(self):
        text = Text("Hello, ManimGL!")
        self.play(Write(text))
        self.wait(2)

運行指令:

manimgl script.py HelloManim

主要特性

常見問題

如果遇到安裝或運行問題,可嘗試:

相關資源



Blender 3D 創作軟體

Blender 是一款開源且全能的 3D 創作軟體,涵蓋了從建模、動畫、渲染到合成與影片編輯的完整管線。它以強大的 Cycles 渲染引擎與靈活的 Python API 著稱,是獨立開發者與中小型工作室的核心工具。


核心技術模組

Blender 的架構設計極為緊湊,透過多個專用引擎協同工作:

技術特性比較

  • 跨平台支援
  • 特性 說明
    Python API 整個 UI 與功能幾乎都能透過 Python 腳本控制,極易開發插件(Add-ons)。 原生支援 Windows、macOS (Apple Silicon) 及 Linux,且檔案格式 (.blend) 全平台通用。
    一體化管線 內建影片剪輯器 (VSE) 與合成器 (Compositor),無需切換軟體即可完成後期製作。

    開發者自動化路徑

    對於需要批量處理 3D 資料或自動化建模的開發者,Blender 提供了強大的後台模式:

    1. 後台渲染: 透過命令列執行 blender -b -P script.py,無需開啟圖形介面即可進行自動化任務。
    2. bpy 模組: Blender 專屬的 Python 函式庫,可操作場景中的每一個頂點、材質與動畫幀。
    3. 自定義 UI: 開發者可以利用 Python 撰寫自定義的面板與工具欄,優化特定工作流。
    注意:Blender 更新速度極快(約每三個月一個版本),開發腳本時需注意不同版本間 API 的相容性變化。


    Blender Python 模組

    bpy 模組是一個專門為 Blender 設計的 Python API,允許使用者在 Blender 內透過程式碼來創建、修改以及管理 3D 圖像和動畫。

    什麼是 bpy

    bpy 是 Blender Python 的縮寫,它是一組函數庫,允許使用 Python 腳本來操作 Blender 的核心功能。透過 bpy,使用者可以:

    bpy 的主要模組和功能

    bpy 包含了多個子模組,每個模組都有特定的用途:

    簡單範例:創建一個立方體

    以下是使用 bpy 創建立方體的簡單範例:

    
    import bpy
    
    # 刪除現有物件
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete(use_global=False)
    
    # 添加立方體
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0))
    
        

    為什麼使用 bpy

    使用 bpy 讓你可以將重複的工作自動化,並且生成複雜的模型、動畫和渲染。對於遊戲設計師、建築師、動畫師等專業人士來說,bpy 提供了強大的工具來優化工作流程。

    參考資料

    欲了解更多關於 bpy 模組的細節,請參考官方文件:Blender Python API Documentation



    遊戲程式開發

    Unity

    Unity 是一個功能強大的遊戲開發引擎和平臺,專門設計用於創建 2D 和 3D 遊戲、互動應用程式及虛擬現實 (VR) 和增強現實 (AR) 體驗。它提供簡單易用的介面和豐富的工具,適合初學者和專業開發人員使用。

    1. Unity 的主要特點
    2. Unity 的核心組件
    3. Unity 的應用範疇
    4. Unity 的優勢

    Unity 是一個強大且靈活的開發引擎,為開發者提供了廣泛的應用場景和工具支持。無論是初學者還是專業開發人員,都可以利用 Unity 快速創建高質量的 2D、3D 遊戲及互動應用。



    Cocos 遊戲引擎

    Cocos 是一個全球領先的開源移動遊戲開發框架,包含早期純程式碼驅動的 Cocos2d-x 以及現代化的全功能編輯器 Cocos Creator。它以輕量、高效及跨平台支援著稱,是開發 2D 與 3D 手遊、小遊戲(如微信小遊戲、TikTok 小遊戲)的首選工具。


    核心產品演進

    Cocos 家族主要分為兩個重要的發展階段,滿足不同開發習慣的需求:

    技術優勢與特性

    特性 說明
    極致跨平台 支援 iOS、Android、Windows、Mac 以及各類 Web 瀏覽器與即時玩小遊戲平台。
    高性能渲染器 底層採用自研的 GFX 抽象層,支援多種圖形後端如 Vulkan、Metal、DirectX 與 WebGL。
    輕量化體積 引擎核心小巧,封裝後的遊戲啟動速度快,適合網路環境受限或對讀取速度要求高的平台。
    TypeScript 支援 Cocos Creator 深度整合 TypeScript,提供完善的型別檢查與語法提示,降低大型專案維護難度。

    核心功能組件

    1. 場景管理: 採用節點(Node)與組件(Component)架構,開發者可輕鬆管理複雜的層級關係。
    2. 物理引擎: 內建支援多種物理後端(如 Box2D、Bullet、Cannon.js),可根據專案需求切換。
    3. UI 系統: 提供靈活的佈局組件、座標轉換與自動合圖功能,大幅優化介面渲染效率。
    4. 動畫系統: 支援骨骼動畫(Spine, DragonBones)、關鍵影格動畫以及自研的 Marionette 動態狀態機。
    注意:Cocos Creator 目前已演進至 3.x 版本,完全整合了 2D 與 3D 的核心技術,開發者可在同一個專案中混合製作 2D UI 與 3D 場景。


    聲音程式開發

    語音合成開發

    核心開發流程

    開發一個語音合成系統通常分為三個階段。首先是前端處理,將原始文本轉化為語言學特徵(如分詞、音標轉換、韻律預測);接著是聲學模型,將這些特徵映射成聲學表示(如梅爾頻譜);最後是聲碼器 (Vocoder),負責將聲學表示還原成人類可聽的波形音頻。

    主流開發框架與庫

    類別 工具/模型 開發特色
    開源框架 Coqui TTS / ESPnet 模組化設計,支援大量預訓練模型與 Fine-tuning
    輕量化引擎 MeloTTS / Kokoro CPU 友善,適合邊緣運算或嵌入式設備
    對話優化 ChatTTS 專為口語對話設計,支援插入笑聲、口頭禪等細節
    研究級模型 StyleTTS 2 / VITS 基於生成對抗網路 (GAN),音質極其接近真人

    自定義模型訓練 (Fine-tuning)

    若要開發具備特定音色的 TTS,你需要準備高品質的數據集(通常為 1 到 10 小時的錄音與對應文本)。開發者常使用 Transfer Learning (遷移學習) 技術,在大型基礎模型上進行微調,這能顯著降低數據量需求並提升聲音的相似度與自然度。

    API 整合開發

    對於大多數應用開發者而言,直接調用成熟的雲端 API 是最高效的方案。例如 ElevenLabs API 提供極強的情感表達,Microsoft Azure Speech SDK 提供最完整的 SSML (語音合成標記語言) 支援,讓開發者能透過標籤精準控制停頓、重音與語氣。此外,OpenAI TTS API 則以簡潔的介面與極低的推理延遲深受即時互動應用喜愛。

    技術選型建議

    在開發初期,建議優先考量「延遲度 (RTF)」與「音質」的平衡。若應用於即時客服,低延遲的流式傳輸 (Streaming) 是關鍵;若應用於有聲書,則應優先追求具備長文本處理能力與豐富韻律感的模型。此外,需注意各國語言的 G2P (字元轉音素) 支援情況,這直接決定了發音的正確認識。



    CosyVoice 2

    CosyVoice 2 是阿里巴巴開源的語音合成(TTS)模型進階版。相比於第一代,它在發音準確性、情感控制細粒度以及流式推理延遲上取得了顯著突破。它不僅支援高品質的音色克隆,更引入了指令可控技術,讓 AI 說話更具「人味」。


    核心技術升級

    CosyVoice 2 採用了「文本-語音語言模型」與「流匹配(Flow Matching)」技術,實現了端到端的語音生成:

    功能特性對照

    功能 CosyVoice 2 說明
    多語言支援 支援中、英、日、韓以及多種方言(粵語、四川話、上海話、天津話等)。
    情感/指令控制 可透過指令(如「開心地說」、「憤怒地說」)控制語音情緒與語速。
    3 秒極速克隆 只需 3 至 10 秒的樣本音訊,即可實現 Zero-shot 高保真音色復刻。
    混合語種合成 支援在同一段文字中混合中英多語言,且音色保持高度一致。

    應用場景與開發建議

    1. 智能客服與虛擬助手: 利用其 150ms 的超低延遲,打造反應迅速且帶有情感溫度的對話系統。
    2. 有聲書與影視配音: 透過細粒度的語氣標籤控制,模擬不同角色的情緒起伏與說話風格。
    3. 教育與方言保護: 內建豐富的方言數據集,可用於數位方言教學或地方文化內容創作。
    注意:在本地部署 CosyVoice 2 時,建議配備至少 8GB 顯存的 NVIDIA 顯示卡,並使用官方推薦的 vLLM 加速框架以獲得最佳的 RTF(實時率)表現。


    CosyVoice 2 基本使用

    CosyVoice 2 基於 Python 開發,由於涉及複雜的音訊處理與深度學習環境,強烈建議使用 Conda 虛擬環境進行隔離安裝。目前官方針對 Linux 支援度最高,Windows 用戶則建議透過 WSL2 或特定的社群修正版進行部署。


    一、環境準備與安裝

    在開始前,請確保您的系統已安裝 NVIDIA 驅動程式(建議顯存 8GB 以上)以及 Conda。

    1. 建立虛擬環境:
      conda create -n cosyvoice2 python=3.10
      conda activate cosyvoice2
    2. 安裝關鍵依賴 Pynini:

      Pynini 是處理文本規範化的核心組件,必須透過 conda 安裝:

      conda install -y -c conda-forge pynini==2.1.5
    3. 複製專案與安裝依賴:
      git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git
      cd CosyVoice
      pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

    二、模型下載

    CosyVoice 2 需要下載預訓練模型權重。您可以透過 Python 腳本自動下載:

    from modelscope import snapshot_download
    # 下載 0.5B 主模型
    snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B')
    # 下載文本規範化資源
    snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd')

    三、基本使用方式

    CosyVoice 2 提供多種模式,滿足從快速配音到專業克隆的需求:

    使用模式 操作說明 適用場景
    啟動 WebUI 執行 python webui.py,在瀏覽器開啟可視化介面。 手動配音、快速測試效果。
    3秒極速復刻 上傳 3-10 秒參考音頻與對應文字,實現音色克隆。 個性化語音包、自媒體配音。
    跨語言/方言 輸入中文文字,選擇粵語或四川話音色輸出。 在地化內容製作。
    指令控制 在文字前加上指令(如:[laughter]、[angry])。 有聲書、戲劇化配音。

    四、開發者 API 調用範例

    如果您想將 CosyVoice 2 整合進自己的 Python 專案(如 Kdenlive 的自動化腳本):

    from cosyvoice.cli.cosyvoice import CosyVoice2
    import torchaudio
    
    # 初始化模型
    cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B')
    
    # 執行推理 (以預訓練音色為例)
    output = cosyvoice.inference_sft('你好,我是人工智慧語音助手。', '中文女')
    
    # 儲存音訊
    torchaudio.save('output.wav', output['tts_speech'], cosyvoice.sample_rate)
    注意:如果您在 Windows 上安裝遇到 sox 或編譯錯誤,可以參考 GitHub Issue #1046,或嘗試使用一鍵安裝包。


    CosyVoice 2 長文章合成

    文本分割與語法完整性

    長文章生成的核心在於預處理。由於 TTS 模型通常有推理長度上限(Context Window),直接輸入過長文本會導致模型輸出亂碼或直接切斷。程式碼中使用正則表達式精準捕捉句末標點,確保切分點位在語氣停頓處,維持合成音質的自然度。

    Tensor 拼接技術

    本程式碼採用 PyTorch 原生方法 torch.cat 處理音訊。相較於將每段音訊先存成檔案再合併,直接在 GPU/CPU 記憶體中對 Tensor 進行拼接能大幅減少磁碟 I/O 開銷,並有效消除段落間可能產生的數位雜音。

    硬體資源與效能

    CosyVoice2 模型較大,建議在具備 NVIDIA GPU 的環境執行以獲得最佳生成速度。處理長文章時,系統會逐段進行推理,若顯存(VRAM)較小,可適度調降 segment_text 函數中的 limit 參數,以換取更穩定的執行過程。
    
    import os
    import torch
    import torchaudio
    import re
    from cosyvoice.cli.cosyvoice import CosyVoice
    
    # 初始化 CosyVoice2 模型
    # 確保路徑指向包含核心權重與設定檔的資料夾
    cosyvoice = CosyVoice('pretrained_models/CosyVoice2-0.5B')
    
    def segment_text(text, limit=80):
        """
        依據標點符號將長文章切分為適當長度的片段,避免語音生成中斷或記憶體溢出
        """
        # 鎖定中文與英文常見句末標點
        pattern = r'([。!?;!\?\n])'
        parts = re.split(pattern, text)
        
        chunks = []
        current = ""
        for i in range(0, len(parts)-1, 2):
            sentence = parts[i] + parts[i+1]
            if len(current) + len(sentence) <= limit:
                current += sentence
            else:
                if current:
                    chunks.append(current.strip())
                current = sentence
        
        if current:
            chunks.append(current.strip())
        return [c for c in chunks if c]
    
    def run_tts_pipeline(text, spk_id, file_name):
        """
        執行長文本推理並在 Tensor 層級進行音訊合併
        """
        text_list = segment_text(text)
        combined_tensors = []
        
        print(f"處理中,文章已切分為 {len(text_list)} 個區段")
        
        for idx, segment in enumerate(text_list):
            # 呼叫 CosyVoice2 推理介面
            # 可切換為 inference_zero_shot 使用參考音頻
            result = cosyvoice.inference_sft(segment, spk_id)
            combined_tensors.append(result['tts_speech'])
            print(f"已完成: {idx + 1}/{len(text_list)}")
    
        if combined_tensors:
            # 使用 torch.cat 進行無縫拼接
            final_audio = torch.cat(combined_tensors, dim=1)
            # 儲存為 wav,建議採樣率為 22050Hz
            torchaudio.save(file_name, final_audio, 22050)
            print(f"任務成功!檔案儲存至: {file_name}")
    
    if __name__ == "__main__":
        long_content = "在此貼入你的長篇文章內容,這段程式碼會自動處理斷句與合併。"
        run_tts_pipeline(long_content, '中文女', 'output_v2.wav')
    
    


    CosyVoice 2 字幕同步生成

    時間戳記對齊邏輯

    要生成準確的 SRT 字幕,核心在於獲取每一段音訊的精確長度(Duration)。在 PyTorch 處理音訊張量時,可以透過採樣率(Sample Rate)與張量長度計算出精確秒數,從而建立起文字與時間軸的對應關係。

    自動化生成流程

    此程式碼在執行語音合成的同時,會記錄每一段文本的起始與結束時間,並自動格式化為標準的 SRT 檔案,方便匯入 Kdenlive 或其他剪輯軟體。
    
    import torch
    import torchaudio
    import re
    from cosyvoice.cli.cosyvoice import CosyVoice
    
    # 初始化 CosyVoice 2
    cosyvoice = CosyVoice('pretrained_models/CosyVoice2-0.5B')
    
    def format_srt_time(seconds):
        """將秒數轉換為 SRT 時間格式 HH:MM:SS,mmm"""
        milliseconds = int((seconds - int(seconds)) * 1000)
        seconds = int(seconds)
        minutes, seconds = divmod(seconds, 60)
        hours, minutes = divmod(minutes, 60)
        return f"{hours:02}:{minutes:02}:{seconds:02},{milliseconds:03}"
    
    def generate_audio_and_srt(full_text, speaker_id, output_wav, output_srt):
        # 按標點符號切分長文章
        segments = re.split(r'([。!?;!\?\n])', full_text)
        chunks = []
        for i in range(0, len(segments)-1, 2):
            text = (segments[i] + segments[i+1]).strip()
            if text: chunks.append(text)
    
        audio_list = []
        srt_entries = []
        current_time = 0.0
        sample_rate = 22050
    
        print(f"開始處理 {len(chunks)} 段文本...")
    
        for i, chunk in enumerate(chunks):
            # 推理生成語音張量
            output = cosyvoice.inference_sft(chunk, speaker_id)
            audio_tensor = output['tts_speech']
            audio_list.append(audio_tensor)
    
            # 計算該段音訊持續秒數 (張量長度 / 採樣率)
            duration = audio_tensor.shape[1] / sample_rate
            end_time = current_time + duration
    
            # 建立 SRT 條目
            srt_entries.append(
                f"{i+1}\n"
                f"{format_srt_time(current_time)} --> {format_srt_time(end_time)}\n"
                f"{chunk}\n"
            )
    
            current_time = end_time
            print(f"已完成第 {i+1} 段對齊")
    
        # 合併並儲存音訊
        combined_audio = torch.cat(audio_list, dim=1)
        torchaudio.save(output_wav, combined_audio, sample_rate)
    
        # 儲存 SRT 檔案
        with open(output_srt, 'w', encoding='utf-8') as f:
            f.write("\n".join(srt_entries))
    
        print(f"完成!音訊:{output_wav}, 字幕:{output_srt}")
    
    if __name__ == "__main__":
        article = "這是一段長文章範例。[laughter] 我們可以精確地計算每一句說話的時間。這樣匯入 Kdenlive 就會自動對齊了。"
        generate_audio_and_srt(article, '中文女', 'output.wav', 'output.srt')
    
    

    匯入剪輯軟體注意事項

    在使用生成的 SRT 與 WAV 檔時,請注意以下幾點:

    CosyVoice 2 指令控制

    情感與非語言符號控制

    CosyVoice 2 支援在文本中插入特定標籤來控制語音的情緒展現或加入非語言動作。這些標籤能顯著提升合成語音的擬真度,讓 AI 不再只是生硬地閱讀,而是帶有情感起伏的表達。

    核心標籤列表

    使用時請將標籤直接嵌入文本中,建議在標籤前後保留適當空格以獲得最佳銜接效果:

    長文章處理與標籤嵌入

    在處理長文本時,邏輯應包含對這些特殊標籤的保留,確保切分算法不會將標籤從中切斷。以下程式碼展示了如何在長文本流程中應用這些指令。
    
    import os
    import torch
    import torchaudio
    import re
    from cosyvoice.cli.cosyvoice import CosyVoice
    
    # 初始化模型
    cosyvoice = CosyVoice('pretrained_models/CosyVoice2-0.5B')
    
    def segment_text_with_tags(text, limit=100):
        """
        切分長文本,同時確保標籤如 [laughter] 不會被切割
        """
        # 匹配中文標點符號與換行
        pattern = r'([。!?;!\?\n])'
        parts = re.split(pattern, text)
        
        chunks = []
        current = ""
        for i in range(0, len(parts)-1, 2):
            sentence = parts[i] + parts[i+1]
            if len(current) + len(sentence) <= limit:
                current += sentence
            else:
                if current:
                    chunks.append(current.strip())
                current = sentence
        
        if current:
            chunks.append(current.strip())
        return chunks
    
    def generate_expressive_audio(text, spk_id, output_path):
        """
        生成包含情感指令的長語音
        """
        segments = segment_text_with_tags(text)
        audio_data = []
    
        for idx, seg in enumerate(segments):
            # 使用 instruct 模式以獲得更佳的標籤執行效果
            # 若使用 sft 模式亦支援基礎標籤,但 instruct 模式對情感控制更精確
            output = cosyvoice.inference_instruct(seg, spk_id, '控制語氣與情感')
            audio_data.append(output['tts_speech'])
            print(f"處理段落 {idx+1}/{len(segments)}")
    
        if audio_data:
            final_wav = torch.cat(audio_data, dim=1)
            torchaudio.save(output_path, final_wav, 22050)
            print(f"含有情感指令的音訊已儲存:{output_path}")
    
    if __name__ == "__main__":
        # 範例:嵌入情感標籤的長文本
        rich_text = "這是一個非常棒的消息! [laughter] 我簡直不敢相信這是真的。 [surprise] 但如果事情搞砸了, [angry] 我會非常生氣。"
        generate_expressive_audio(rich_text, '中文女', 'expressive_output.wav')
    
    


    語音辨識開發

    開發流程與關鍵階段

    開發 ASR (Automatic Speech Recognition) 系統通常遵循以下核心路徑。首先是音訊預處理(如降噪、VAD 語音活動偵測與特徵提取);接著進入模型推論,將聲學訊號轉化為文字機率;最後透過後處理(如標點符號恢復、逆文字正規化 ITN)產出最終文本。現代開發趨勢已從傳統的 HMM 轉向「端到端 (End-to-End)」神經網路架構,大幅簡化了開發複雜度。

    主流 ASR 開發模型與框架

    類別 工具/模型 2026 年開發特點
    基礎模型 OpenAI Whisper (V3) 產業標準,具備極強的抗噪能力與多語種支援,最適合長音檔轉錄。
    即時串流 NVIDIA Parakeet-TDT 專為超低延遲設計,支援串流辨識 (Streaming),適合 AI 語音助手。
    國產優化 FunASR / 雅廷引擎 對中文、中英夾雜與台灣口音有深度優化,支援時間戳與發音人辨識。
    部署框架 Faster-Whisper / Sherpa-ONNX 大幅提升推論速度並降低記憶體佔用,適合在邊緣設備或本地伺服器運行。

    開發者面臨的技術指標

    在開發 ASR 系統時,需重點監控 CER (字符錯誤率) 以評估準確性。針對即時應用,RTF (即時係數)延遲 (Latency) 至關重要,必須確保語音處理速度遠快於說話速度。2026 年的開發重點已轉向「長文本記憶」與「上下文感知」,例如整合 LLM 來修正專業術語或特定行業別的辨識偏見。

    API 與雲端整合開發

    若追求快速上線,開發者通常會調用雲端 API。DeepgramAssemblyAI 在 2026 年以低延遲與豐富的 metadata(如情緒偵測、重點摘要)受到青睞。Microsoft Azure Speech SDK 則提供最完整的自定義模型微調 (Custom Speech) 介面,允許開發者上傳特定領域的文本數據,解決醫療、法律等特殊詞彙辨識不準的問題。

    部署與環境選型建議

    對於個人開發者,建議使用 Hugging Face Transformers 庫搭配 PyTorch 進行快速實驗。若應用場景涉及隱私(如醫療記錄),應採用 Whisper.cppVosk 進行完全離線的本地部署。若需構建大型語音服務,則建議採用 Triton Inference ServerDocker 容器化技術,實現 ASR 模型的高效調度與擴展。



    JavaScript 畫圖

    Canvas 與 Context

    Canvas 的基本概念

    HTML5 的 <canvas> 元素是一個可供使用 JavaScript 繪圖的區域,允許在網頁上呈現 2D 和 3D 圖像。它是一個容器,可以透過程式碼進行繪製操作,如畫線、圖形和圖片,適合遊戲、圖形編輯等需要即時生成的應用。

    以下是 canvas 元素的基本語法:

    <canvas id="myCanvas" width="500" height="500"></canvas>

    getContext 的作用

    要在 canvas 元素上繪製內容,必須使用 getContext 方法。這個方法允許取得繪圖的上下文,目前最常用的選項是 "2d"。它會返回一個 CanvasRenderingContext2D 物件,提供許多繪圖方法。

    例如,以下 JavaScript 程式碼可以取得 canvas 的 2D 繪圖上下文:

    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");

    基本繪圖操作

    使用 getContext("2d") 獲得的繪圖上下文,能夠進行如畫線、畫矩形、填充顏色等基本繪圖操作。例如:

    範例程式碼:

    ctx.fillStyle = "blue";
    ctx.fillRect(50, 50, 100, 100); // 畫一個藍色矩形
    ctx.strokeStyle = "red";
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(200, 200);
    ctx.stroke(); // 畫一條紅色線條

    清除 Canvas

    若要清除 canvas 中的圖像,可以使用 clearRect(x, y, width, height) 方法。例如,清除整個畫布的程式碼為:

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    動態繪圖與動畫

    利用 requestAnimationFrame() 可以實現平滑的動畫效果。透過每次更新畫面前先清除上一幀的內容,可以繪製出動態效果。以下是簡單的動畫範例:

    function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillRect(x, y, 50, 50); // 繪製方塊
    x += 1; // 更新位置
    requestAnimationFrame(draw);
    }
    draw();

    Canvas 使用注意事項

    Canvas 的尺寸應設定在 HTML 中,若使用 CSS 改變大小可能導致畫面失真。此外,canvas 並非為了代替高解析度的影像,而是用來即時生成和動態繪圖。



    style.transform

    基本概念

    style.transform 是 CSS 的屬性之一,可用來對元素進行旋轉、縮放、位移、傾斜等 2D 或 3D 轉換操作。

    scale() 則是其中的「縮放」函式,語法為:

    
    transform: scale(sx [, sy]);
    

    其中:

    ---

    JavaScript 設定方式

    
    const el = document.getElementById("target");
    el.style.transform = "scale(1.5)";  // x與y都放大1.5倍
    
    
    el.style.transform = "scale(1.5, 0.5)"; // 水平放大1.5倍,垂直縮小為一半
    
    ---

    與寬高無關,但會影響視覺尺寸

    scale() 是一種「視覺轉換」,它不會改變元素的實際 DOM 屬性(如 offsetWidthclientWidth),但會改變 getBoundingClientRect() 的回傳值。

    
    el.getBoundingClientRect().width  // 會反映 scale 的影響
    el.offsetWidth                    // 原始寬度,不受 scale 影響
    
    ---

    常見應用

    ---

    範例

    
    <style>
      #box {
        width: 100px;
        height: 100px;
        background: skyblue;
        transition: transform 0.3s;
      }
      #box:hover {
        transform: scale(1.5);
      }
    </style>
    
    <div id="box"></div>
    
    ---

    注意事項



    Canvas 畫圓餅圖

    範例說明

    以下範例從 HTML <table> 讀取資料,使用原生 <canvas> API 的 arc() 繪製圓餅圖,不需任何外部套件。

    ---

    HTML 結構

    
    <table id="dataTable" border="1" style="margin:10px auto;">
      <tr><th>類別</th><th>數值</th></tr>
      <tr><td>蘋果</td><td>30</td></tr>
      <tr><td>香蕉</td><td>15</td></tr>
      <tr><td>櫻桃</td><td>25</td></tr>
      <tr><td>芒果</td><td>20</td></tr>
    </table>
    
    <canvas id="pieCanvas" width="400" height="400" style="display:block; margin:auto; border:1px solid #aaa;"></canvas>
    
    ---

    JavaScript 程式

    
    const table = document.getElementById("dataTable");
    const canvas = document.getElementById("pieCanvas");
    const ctx = canvas.getContext("2d");
    
    const labels = [];
    const values = [];
    
    for (let i = 1; i < table.rows.length; i++) { // 跳過表頭
      const row = table.rows[i];
      labels.push(row.cells[0].textContent);
      values.push(parseFloat(row.cells[1].textContent));
    }
    
    // 計算總和
    const total = values.reduce((a, b) => a + b, 0);
    
    // 繪製圓餅圖
    let startAngle = 0;
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const radius = 120;
    
    // 自動配色
    const colors = ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF", "#FF9F40"];
    
    for (let i = 0; i < values.length; i++) {
      const sliceAngle = (values[i] / total) * 2 * Math.PI;
      const endAngle = startAngle + sliceAngle;
    
      // 畫圓餅區塊
      ctx.beginPath();
      ctx.moveTo(centerX, centerY);
      ctx.arc(centerX, centerY, radius, startAngle, endAngle);
      ctx.closePath();
      ctx.fillStyle = colors[i % colors.length];
      ctx.fill();
    
      // 標示文字
      const midAngle = startAngle + sliceAngle / 2;
      const textX = centerX + Math.cos(midAngle) * (radius + 20);
      const textY = centerY + Math.sin(midAngle) * (radius + 20);
      ctx.fillStyle = "black";
      ctx.font = "14px sans-serif";
      ctx.textAlign = "center";
      ctx.fillText(labels[i], textX, textY);
    
      startAngle = endAngle;
    }
    
    // 標題
    ctx.font = "16px bold sans-serif";
    ctx.textAlign = "center";
    ctx.fillText("水果銷售比例", centerX, centerY - radius - 30);
    
    ---

    說明

    ---

    延伸

    你可以加入滑鼠事件(例如 hover 放大或顯示百分比),或用 requestAnimationFrame() 加上動畫效果。是否要我幫你加上滑鼠 hover 顯示資料百分比的版本?



    SVG

    概念

    SVG(Scalable Vector Graphics)是一種基於 XML 的向量圖形格式,可在網頁中繪製線條、圖形、文字,並支援縮放與動畫。與點陣圖不同,SVG 在放大縮小時不會失真,適合圖表、ICON、地圖與流程圖等應用。

    特點

    基本語法範例

    
    <svg width="200" height="100">
      <rect x="10" y="10" width="50" height="50" fill="blue" />
      <circle cx="100" cy="35" r="25" fill="green" />
      <line x1="150" y1="10" x2="190" y2="60" stroke="red" stroke-width="2" />
      <text x="10" y="90" font-size="14" fill="black">這是SVG</text>
    </svg>
    

    常用元素

    事件與互動

    
    <svg width="100" height="100">
      <circle cx="50" cy="50" r="40" fill="orange" onclick="alert('你點到了圓形')" />
    </svg>
    

    動畫與樣式

    可透過 CSS<animate> 標籤製作動畫:

    
    <circle cx="30" cy="50" r="20" fill="blue">
      <animate attributeName="cx" from="30" to="170" dur="2s" repeatCount="indefinite" />
    </circle>
    

    與 JavaScript 結合

    
    <svg id="mysvg" width="200" height="100">
      <circle id="c1" cx="50" cy="50" r="30" fill="gray" />
    </svg>
    
    <script>
      document.getElementById("c1").setAttribute("fill", "red");
    </script>
    

    應用範圍

    結論

    SVG 是網頁前端中非常重要的圖形標準之一,具有高解析度、互動性與動畫性,並可與 HTML/CSS/JavaScript 無縫整合。適合需要精確、縮放性強的圖形表現場景。



    SVG 重複使用圖案

    目的

    在 SVG 中可透過 <symbol><defs> 定義一次圖案,再用 <use> 在其他地方重複引用,節省代碼並提高一致性。

    基本語法

    
    <svg width="0" height="0" style="position:absolute">
      <symbol id="star" viewBox="0 0 100 100">
        <polygon points="50,5 61,39 98,39 68,59 79,91 50,70 21,91 32,59 2,39 39,39"
                 fill="gold" stroke="black" stroke-width="2"/>
      </symbol>
    </svg>
    
    <svg width="200" height="100">
      <use href="#star" x="0" y="0" width="50" height="50"/>
      <use href="#star" x="60" y="0" width="50" height="50" fill="red"/>
      <use href="#star" x="120" y="0" width="50" height="50" fill="blue"/>
    </svg>
    

    展示

    說明

    屬性繼承

    <use> 可改變 fillstroke 等屬性,覆蓋原始定義。

    應用範圍

    相容性

    結論

    透過 <symbol> + <use>,SVG 可實現元件化、模組化圖形開發,既可重複使用也方便管理樣式與位置,非常適合圖示設計與資料視覺化應用。



    WebGL

    概念

    WebGL(Web Graphics Library)是一套基於 OpenGL ES 的 JavaScript API,可在瀏覽器中使用 HTML5 的 <canvas> 元素進行 2D 和 3D 圖形的硬體加速繪製,不需要任何外掛。

    特點

    簡單範例

    繪製一個有顏色的三角形:

    
    <canvas id="glCanvas" width="300" height="300"></canvas>
    <script>
      const canvas = document.getElementById('glCanvas');
      const gl = canvas.getContext('webgl');
    
      if (!gl) {
        alert("你的瀏覽器不支援 WebGL");
      }
    
      const vertexShaderSource = `
        attribute vec2 a_position;
        void main() {
          gl_Position = vec4(a_position, 0, 1);
        }
      `;
    
      const fragmentShaderSource = `
        void main() {
          gl_FragColor = vec4(1, 0, 0, 1); // 紅色
        }
      `;
    
      function createShader(gl, type, source) {
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        return shader;
      }
    
      const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
      const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
    
      const program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
    
      gl.useProgram(program);
    
      const positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0, 1,
       -1, -1,
        1, -1
      ]), gl.STATIC_DRAW);
    
      const posAttribLoc = gl.getAttribLocation(program, "a_position");
      gl.enableVertexAttribArray(posAttribLoc);
      gl.vertexAttribPointer(posAttribLoc, 2, gl.FLOAT, false, 0, 0);
    
      gl.clearColor(0, 0, 0, 1);
      gl.clear(gl.COLOR_BUFFER_BIT);
      gl.drawArrays(gl.TRIANGLES, 0, 3);
    </script>
    

    顯示

    應用範圍

    常用套件

    結論

    WebGL 為網頁開發者提供 GPU 加速的 3D 圖形繪製能力,是現代 Web 遊戲、數位藝術、模擬與視覺化的核心技術之一。雖然原生 WebGL 較為底層,但可搭配高階函式庫簡化開發流程。



    Spirograph

    什麼是 Spirograph?

    Spirograph 是一種用於創建複雜圖形的幾何圖案,其原理是利用兩個圓形的轉動來描繪出多重圓形和波浪形的曲線。這種圖形通常用於藝術創作和教育,能夠展現數學中的幾何美感。

    在 HTML5 中實作 Spirograph

    以下是使用 HTML5 的 <canvas> 元素和 JavaScript 實現 Spirograph 的範例:



    向量圖 JavaScript 程式庫比較

    程式庫名稱 語法表達性 圖形類型 適合對象 是否支援互動 是否支援動畫
    Mermaid.js 極高(使用類 Markdown 語法) 流程圖、序列圖、甘特圖、ER圖、Class圖 文件視覺化、快速原型 有限支援 部分支援
    D3.js 中等(需要理解資料綁定與 DOM 操作) 幾乎所有圖形(自訂性極高) 進階資料視覺化開發者 完整支援 完整支援
    Cytoscape.js 高(以 JSON 定義節點與邊) 網路圖、流程圖 生物資訊、社交網絡分析 完整支援 部分支援
    Vega / Vega-Lite 高(使用 JSON 宣告式描述圖表) 統計圖表(條狀圖、散佈圖等) 資料科學、儀表板設計 支援 部分支援
    Graphviz via Viz.js 高(DOT 語法類似文字編程) 流程圖、圖論結構 學術用途、快速架構圖 不支援 不支援
    JSXGraph 高(幾何語意清晰) 幾何圖形、座標圖 數學教育 支援 支援


    Chart.js

    概述

    Chart.js 是一個開源、輕量級且功能強大的 JavaScript 圖表繪製函式庫, 可在 HTML5 的 <canvas> 元素上繪製各種互動式圖表。 它以簡潔的 API、漂亮的預設樣式與高度可客製化的選項著稱, 適合快速將資料可視化於網站或應用程式中。

    ---

    主要特色

    ---

    安裝與使用

    1. CDN 載入

    
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    

    2. NPM 安裝

    
    npm install chart.js
    

    3. 基本用法範例

    
    <canvas id="myChart"></canvas>
    
    <script>
    const ctx = document.getElementById('myChart').getContext('2d');
    
    new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['紅色', '藍色', '黃色', '綠色', '紫色', '橘色'],
        datasets: [{
          label: '票數',
          data: [12, 19, 3, 5, 2, 3],
          backgroundColor: [
            'rgba(255, 99, 132, 0.6)',
            'rgba(54, 162, 235, 0.6)',
            'rgba(255, 206, 86, 0.6)',
            'rgba(75, 192, 192, 0.6)',
            'rgba(153, 102, 255, 0.6)',
            'rgba(255, 159, 64, 0.6)'
          ],
          borderWidth: 1
        }]
      },
      options: {
        responsive: true,
        scales: {
          y: { beginAtZero: true }
        }
      }
    });
    </script>
    
    ---

    常見圖表類型

    圖表類型設定 type用途說明
    折線圖line顯示時間序列或趨勢資料。
    長條圖bar比較不同分類的數值。
    圓餅圖pie顯示整體比例分配。
    甜甜圈圖doughnut圓餅圖的變體,中央可留白顯示標題。
    雷達圖radar多維度資料的比較。
    極區圖polarArea結合圓餅與長條的效果。
    ---

    版本檢查

    可以使用下列方式檢查 Chart.js 的版本:

    
    console.log(Chart.version);
    
    ---

    優缺點

    優點:

    缺點:

    ---

    官方資源



    畫圓餅圖 - Chart.js

    範例說明

    以下範例示範如何從 HTML <table> 讀取資料,並使用 JavaScript 動態繪製圓餅圖。此範例使用 Chart.js,簡單易用且支援自動配色與動畫。

    ---

    HTML 結構

    
    <!-- 表格資料 -->
    <table id="dataTable" border="1" style="margin:10px auto;">
      <tr><th>類別</th><th>數值</th></tr>
      <tr><td>蘋果</td><td>30</td></tr>
      <tr><td>香蕉</td><td>15</td></tr>
      <tr><td>櫻桃</td><td>25</td></tr>
      <tr><td>芒果</td><td>20</td></tr>
    </table>
    
    <!-- 圓餅圖容器 -->
    <canvas id="pieChart" width="400" height="400"></canvas>
    
    <!-- 載入 Chart.js -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    
    ---

    JavaScript 程式

    
    // 讀取表格資料
    const table = document.getElementById("dataTable");
    const labels = [];
    const values = [];
    
    for (let i = 1; i < table.rows.length; i++) { // 跳過表頭
      const row = table.rows[i];
      labels.push(row.cells[0].textContent);
      values.push(parseFloat(row.cells[1].textContent));
    }
    
    // 建立 Chart.js 圓餅圖
    const ctx = document.getElementById("pieChart").getContext("2d");
    new Chart(ctx, {
      type: "pie",
      data: {
        labels: labels,
        datasets: [{
          data: values,
          backgroundColor: [
            "rgba(255, 99, 132, 0.7)",
            "rgba(54, 162, 235, 0.7)",
            "rgba(255, 206, 86, 0.7)",
            "rgba(75, 192, 192, 0.7)"
          ],
          borderColor: "white",
          borderWidth: 2
        }]
      },
      options: {
        responsive: true,
        plugins: {
          legend: { position: "bottom" },
          title: { display: true, text: "水果銷售比例" }
        }
      }
    });
    
    ---

    說明

    ---

    延伸應用

    若想在純 JavaScript(不使用外部 library)中繪製,可使用 CanvasRenderingContext2D.arc() 自行繪製扇形。要我幫你示範「不使用 Chart.js」的版本嗎?



    使用 HTML 繪製 UML 圖的範例

    1. 使用 SVG 畫出簡單的類別圖

    在 HTML 中,您可以使用 <svg> 標籤來繪製基本的 UML 類別圖。以下是一個範例,展示如何使用矩形和文字來代表一個簡單的類別。

    <svg width="300" height="200">
        <rect x="50" y="20" width="200" height="30" fill="lightblue" stroke="black"/>
        <text x="60" y="40" font-family="Arial" font-size="16">Class Name</text>
        
        <rect x="50" y="50" width="200" height="50" fill="white" stroke="black"/>
        <text x="60" y="70" font-family="Arial" font-size="14">+ attribute1 : Type</text>
        <text x="60" y="90" font-family="Arial" font-size="14">+ attribute2 : Type</text>
        
        <rect x="50" y="100" width="200" height="50" fill="white" stroke="black"/>
        <text x="60" y="120" font-family="Arial" font-size="14">+ method1() : ReturnType</text>
        <text x="60" y="140" font-family="Arial" font-size="14">+ method2() : ReturnType</text>
    </svg>
    
    Class Name + attribute1 : Type + attribute2 : Type + method1() : ReturnType + method2() : ReturnType

    2. 使用 HTML 和 CSS 自訂 UML 元素

    可以利用 HTML 和 CSS 的樣式來定義不同的 UML 元件。下面的範例展示如何使用 <div>CSS 來繪製一個類別框,並調整其樣式來模仿 UML 類別圖的結構。

    <style>
    .class-box {
        width: 200px;
        border: 1px solid black;
        margin: 10px;
    }
    .header {
        background-color: lightblue;
        text-align: center;
        font-weight: bold;
    }
    .attributes, .methods {
        padding: 10px;
        border-top: 1px solid black;
    }
    </style>
    
    <div class="class-box">
        <div class="header">ClassName</div>
        <div class="attributes">
            + attribute1 : Type <br>
            + attribute2 : Type
        </div>
        <div class="methods">
            + method1() : ReturnType <br>
            + method2() : ReturnType
        </div>
    </div>
    
    ClassName
    + attribute1 : Type
    + attribute2 : Type
    + method1() : ReturnType
    + method2() : ReturnType

    3. 使用 mermaid.js 繪製更複雜的 UML 圖

    為了在 HTML 中繪製更複雜的 UML 圖,可以使用 mermaid.js 這樣的外部 JavaScript 庫。它支援多種 UML 圖表,並且可以直接嵌入 HTML。首先需要引用 mermaid.js,然後使用 <pre> 標籤撰寫 UML 圖表定義。

    <script type="module">
    import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
    mermaid.initialize({ startOnLoad: true });
    </script>
    
    <pre class="mermaid">
    classDiagram
        Class01 <|-- Class02 : Inheritance
        Class01 : +method1() void
        Class02 : +method2() void
        Class03 : +attribute int
        Class04 : +method() void
    </pre>
    
    classDiagram
        Class01 <|-- Class02 : Inheritance
        Class01 : +method1() void
        Class02 : +method2() void
        Class03 : +attribute int
        Class04 : +method() void
    

    這樣的範例可以輕鬆地使用 mermaid.js 繪製出更複雜且清晰的 UML 圖,並且支援不同的圖表類型。



    Mermaid 繪製複雜 UML 範例

    範例 1: 複雜的類別關係圖

    此範例展示類別之間的繼承、組合、聚合和關聯。

    <pre class="mermaid">
    classDiagram
        Animal <|-- Mammal
        Animal <|-- Bird
        Mammal o-- Dog : has-a
        Bird --> Wing : has-a
        class Animal {
            +String name
            +int age
            +eat() void
        }
        class Mammal {
            +hasFur() bool
        }
        class Dog {
            +bark() void
        }
        class Bird {
            +fly() void
        }
        class Wing {
            +wingSpan int
        }
    </pre>
    
    classDiagram
        Animal <|-- Mammal
        Animal <|-- Bird
        Mammal o-- Dog : has-a
        Bird --> Wing : has-a
        class Animal {
            +String name
            +int age
            +eat() void
        }
        class Mammal {
            +hasFur() bool
        }
        class Dog {
            +bark() void
        }
        class Bird {
            +fly() void
        }
        class Wing {
            +wingSpan int
        }
    

    說明:此範例展示了多種關係:

    範例 2: 關聯與多重性

    此範例展示如何在類別之間表示多重性(1..*、0..1 等)和角色。

    <pre class="mermaid">
    classDiagram
        Customer "1" --> "0..*" Order : places
        Order "1" --> "1" Payment : includes
        class Customer {
            +String name
            +String email
            +placeOrder() void
        }
        class Order {
            +int orderId
            +String date
            +calculateTotal() float
        }
        class Payment {
            +float amount
            +String method
            +processPayment() void
        }
    </pre>
    
    classDiagram
        Customer "1" --> "0..*" Order : places
        Order "1" --> "1" Payment : includes
        class Customer {
            +String name
            +String email
            +placeOrder() void
        }
        class Order {
            +int orderId
            +String date
            +calculateTotal() float
        }
        class Payment {
            +float amount
            +String method
            +processPayment() void
        }
    

    說明:

    範例 3: 介面與抽象類別

    此範例展示如何在 Mermaid.js 中定義介面和抽象類別。

    <pre class="mermaid">
    classDiagram
        class Shape {
            <<_abstract_>>
            +area() float
            +perimeter() float
        }
        Shape <|-- Rectangle
        Shape <|-- Circle
        class Rectangle {
            +width float
            +height float
            +area() float
            +perimeter() float
        }
        class Circle {
            +radius float
            +area() float
            +perimeter() float
        }
    </pre>
    
    classDiagram
        class Shape {
            <<_abstract_>>
            +area() float
            +perimeter() float
        }
        
        Shape <|-- Rectangle
        Shape <|-- Circle
        
        class Rectangle {
            +width : float
            +height : float
            +area() float
            +perimeter() float
        }
        
        class Circle {
            +radius : float
            +area() float
            +perimeter() float
        }    
    

    說明:

    範例 4: 複雜的類別與介面實作

    此範例展示類別繼承和介面實作的混合用法。

    <pre class="mermaid">
    classDiagram
        class Flyable {
            <<_interface_>>
            +fly() void
        }
        class Bird {
            +String species
            +String color
            +sing() void
        }
        class Airplane {
            +String model
            +int capacity
            +takeOff() void
        }
        Bird ..|> Flyable : implements
        Airplane ..|> Flyable : implements
    </pre>
    
    classDiagram
        class Flyable {
            <<_interface_>>
            +fly() void
        }
        class Bird {
            +String species
            +String color
            +sing() void
        }
        class Airplane {
            +String model
            +int capacity
            +takeOff() void
        }
        Bird ..|> Flyable : implements
        Airplane ..|> Flyable : implements
    

    說明:



    Mermaid 測試工具

    生成結果

        flowchart TD
        A[開始] --> B{是否需要繼續?}
        B -- 是 --> C[執行操作]
        B -- 否 --> D[結束]
        C --> D
    


    如何檢查 Mermaid 語法錯誤

    1. 使用 Mermaid Live Editor

    Mermaid 提供官方的 Mermaid Live Editor,可以即時測試並檢查語法錯誤。將 Mermaid 語法貼上後,如果有錯誤,編輯器會顯示具體錯誤訊息,讓你更快地排除問題。

    2. 減少複雜性進行測試

    如果你的 Mermaid 圖表過於複雜,建議分段測試。例如,先移除一些類別或關係,只留下最基本的結構,逐步增加元素,這樣可以更快找出可能的語法錯誤來源。

    3. 確認 Mermaid.js 版本

    Mermaid.js 的不同版本可能對語法有不同的支持。確保你使用的是最新版,或者在測試環境中確認你的 Mermaid.js 版本是否支持使用的語法功能。

    4. 檢查常見錯誤

    5. 使用開發者工具查看錯誤訊息

    在瀏覽器的開發者工具中查看 JavaScript console,如果 Mermaid 圖表未正確生成,console 中可能會顯示具體錯誤訊息或提示,幫助你找出語法錯誤。

    6. 參考官方文件

    Mermaid 官方文件提供詳細的語法指南,可以幫助你確認語法使用是否正確。官方文件位於 Mermaid.js 官方網站



    流程圖

    流程圖概述

    以下是一個簡單的流程圖範例,說明決策與行動之間的邏輯關係。

    流程圖範例

    flowchart TD
        A[開始] --> B{是否需要繼續?}
        B -- 是 --> C[執行操作]
        B -- 否 --> D[結束]
        C --> D
        

    範例說明

    如何使用

    將上述流程圖語法粘貼到支持 Mermaid 的工具(如 Markdown 編輯器或 Mermaid 在線工具)中,即可生成出圖形。



    Mermaid.js 縮放滑桿函式庫

    功能說明

    此 JavaScript 函式庫可為 Mermaid.js 圖表加入可縮放的滑桿功能,使用者可透過 <input type="range"> 控制圖表的縮放比例。函式庫使用 transform: scale() 實現視覺縮放,無需重新渲染 Mermaid。

    函式庫程式碼(mermaidZoomSlider.js)

    
    // mermaidZoomSlider.js
    export function setupMermaidZoomSlider({
      sliderId = "zoomSlider",
      diagramContainerId = "mermaidContainer",
      min = 0.1,
      max = 3,
      step = 0.1,
      initial = 1
    } = {}) {
      window.addEventListener("load", () => {
        const slider = document.getElementById(sliderId);
        const container = document.getElementById(diagramContainerId);
    
        if (!slider || !container) {
          console.warn("Mermaid zoom slider: Missing slider or container element");
          return;
        }
    
        // 初始化 slider 屬性
        slider.min = min;
        slider.max = max;
        slider.step = step;
        slider.value = initial;
    
        // 設定初始縮放
        container.style.transformOrigin = "top left";
        container.style.transform = `scale(${initial})`;
    
        // 事件監聽:縮放
        slider.addEventListener("input", () => {
          const scale = parseFloat(slider.value);
          container.style.transform = `scale(${scale})`;
        });
      });
    }
    

    使用方式

    
    <!-- HTML -->
    <div>
      <input type="range" id="zoomSlider">
    </div>
    <div id="mermaidContainer">
      <pre class="mermaid">
        graph TD;
          A-->B;
          B-->C;
      </pre>
    </div>
    
    <!-- JavaScript 模組引入 -->
    <script type="module">
      import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
      import { setupMermaidZoomSlider } from "./mermaidZoomSlider.js";
    
      mermaid.initialize({ startOnLoad: true });
    
      setupMermaidZoomSlider({
        sliderId: "zoomSlider",
        diagramContainerId: "mermaidContainer",
        min: 0.2,
        max: 3,
        step: 0.1,
        initial: 1
      });
    </script>
    

    參數說明

    建議

    若需要拖曳移動、縮放重設等進階功能,可進一步擴充此函式庫,例如整合滑鼠拖拉與縮放重設按鈕。



    Mermaid.js 線條的各種樣式

    基本線條語法

    在 Mermaid.js 的圖中使用 -->===> 等標記來建立節點之間的連線,不同的符號代表不同的線條樣式。

    常見線條樣式

    語法 樣式 說明
    --> ──> 一般實線箭頭
    ---> ───> --> 相同(語法容錯)
    -- text --> ── text ──> 帶文字標籤的實線箭頭
    -.-> -.-> 虛線箭頭
    -. text .-> -. text .-> 帶文字的虛線箭頭
    ==> ===> 粗實線箭頭
    == text ==> == text ==> 帶文字的粗線箭頭
    --o ──○ 圓頭無方向線(class diagram 常用)
    --|> ──▷ 實心箭頭(class diagram 常用)
    --> | label | ──>(帶雙側文字) Mermaid 支援樣式註解標籤

    使用範例

    
    graph TD
      A[開始] --> B[步驟一]
      B -.-> C[非同步處理]
      C ==> D[強烈依賴]
      D -- text --> E[帶文字的連線]
      E --o F[圓頭]
      F --|> G[實心箭頭]
    

    其他說明

    結論

    Mermaid.js 提供多種線條語法樣式,讓使用者能清晰表達流程、邏輯與關聯,透過實線、虛線、粗線與圖示端點等搭配,可建立簡潔又結構分明的圖表。



    D3.js

    什麼是 D3.js?

    D3.js (Data-Driven Documents) 是一個基於 JavaScript 的開源程式庫,用於將數據轉換為動態且互動的可視化效果。它使用網頁標準技術如 SVG、HTML 和 CSS,提供強大的工具來處理數據和繪製圖形。

    D3.js 的特色

    D3.js 的主要功能

    1. 選擇元素: 使用類似 CSS 的選擇器來選擇和操作 DOM 元素,例如:d3.select()d3.selectAll()
    2. 數據綁定: 將數據綁定到 DOM 元素,並根據數據更新視圖。
    3. 縮放與比例尺: 提供縮放工具和比例函數,方便數據映射到像素。
    4. 繪製圖形: 使用 SVG 路徑和形狀工具創建各種圖表,如圓形、矩形和曲線。
    5. 過渡效果: 內建動畫功能,支持平滑的數據變化。

    應用範例

    D3.js 被廣泛應用於各種數據可視化場景,例如:

    學習資源

    要學習 D3.js,可以參考以下資源:

    結論

    D3.js 是一個功能強大且靈活的數據可視化工具,適合需要高度自訂化圖表和互動效果的開發者。雖然學習曲線稍高,但一旦掌握,其應用潛力無窮。



    D3.js 樹狀圖範例

    範例說明

    本範例使用 D3.js 繪製一個簡單的樹狀圖,展示如何將階層結構資料視覺化。以下是主要步驟:

    範例程式碼

    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>D3.js Tree Diagram Example</title>
      <script src="https://d3js.org/d3.v7.min.js"></script>
      <style>
        .node circle {
          fill: steelblue;
        }
        .node text {
          font: 12px sans-serif;
        }
        .link {
          fill: none;
          stroke: #ccc;
          stroke-width: 1.5px;
        }
      </style>
    </head>
    <body>
      <script>
        const width = 800;
        const height = 600;
    
        const treeData = {
          name: "CEO",
          children: [
            {
              name: "CTO",
              children: [
                { name: "Engineering Manager" },
                { name: "Product Manager" }
              ]
            },
            {
              name: "CFO",
              children: [
                { name: "Accountant" },
                { name: "Finance Analyst" }
              ]
            }
          ]
        };
    
        const svg = d3.select("body")
          .append("svg")
          .attr("width", width)
          .attr("height", height)
          .append("g")
          .attr("transform", "translate(40,40)");
    
        const treeLayout = d3.tree().size([height - 100, width - 160]);
    
        const root = d3.hierarchy(treeData);
        treeLayout(root);
    
        svg.selectAll(".link")
          .data(root.links())
          .enter()
          .append("path")
          .attr("class", "link")
          .attr("d", d3.linkHorizontal()
            .x(d => d.y)
            .y(d => d.x)
          );
    
        const nodes = svg.selectAll(".node")
          .data(root.descendants())
          .enter()
          .append("g")
          .attr("class", "node")
          .attr("transform", d => `translate(${d.y},${d.x})`);
    
        nodes.append("circle").attr("r", 5);
    
        nodes.append("text")
          .attr("dy", 3)
          .attr("x", d => d.children ? -10 : 10)
          .style("text-anchor", d => d.children ? "end" : "start")
          .text(d => d.data.name);
      </script>
    </body>
    </html>
    
    

    結果展示

    運行此程式碼後,您將看到一個樹狀圖:

    應用與擴展

    此範例可以擴展至更複雜的階層結構,或調整樣式以適應不同需求。例如:



    矩形樹狀圖 Treemapping

    概念說明

    矩形樹狀圖是一種用巢狀矩形方式來顯示階層資料的視覺化技術。每個矩形的面積代表一個數值大小,例如銷售額或檔案容量,而每個矩形也可以進一步巢狀,用來表示子分類。

    應用場景

    範例 (使用 D3.js 製作)

    優點

    注意事項



    Cytoscape.js 網路圖範例

    基本用法

    Cytoscape.js 是用來繪製網路圖(Graph)的 JavaScript 函式庫,使用 JSON 定義節點與邊,語法簡潔,支援互動與樣式客製化。

    簡單網路圖示例

    說明



    Cytoscape.js 不同應用範例

    1. 環狀排列圖(Circle Layout)

    2. 拖曳與點擊互動

    3. 分群與樣式(Style by Class)

    說明



    JavaScript 電路圖繪製程式庫

    程式庫名稱 適用性 特點 是否支援互動 說明
    JointJS ★★★★★ 繪圖自由度高、可擴充電路元件符號 ✔️ 可繪製邏輯電路、流程圖,免費版功能已足夠
    GoJS ★★★★☆ 強大的圖形與資料模型支援 ✔️ 非自由軟體,但有免費試用;常用於產線圖與電路圖
    SVG.js ★★★☆☆ 輕量、支援精準繪圖 ✔️ 需自行設計元件(電阻、電容等),適合細部控制
    Konva.js ★★★☆☆ Canvas 與 SVG 都支援 ✔️ 適合需要拖曳、點擊等互動行為的設計工具
    ELK.js ★★☆☆☆ 自動佈局優秀 ✖️ 只負責佈局演算法(可與 JointJS 搭配)


    JointJS 顯示基本電路圖元件



    3D 方程式繪圖

    功能說明

    本工具可將以 xy 為自變數的 z = f(x, y) 方程式繪製成 3D 曲面圖,並提供滑鼠操作旋轉、縮放、平移的互動功能。

    HTML 結構

    
    <div id="plot3d" style="width:100%; height:600px;"></div>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script type="module">
      // 定義 z = f(x, y) 的函數(可更換為任意方程式)
      function computeZ(x, y) {
        return Math.sin(x) * Math.cos(y);  // z = sin(x) * cos(y)
      }
    
      const xRange = numeric.linspace(-5, 5, 50);
      const yRange = numeric.linspace(-5, 5, 50);
    
      // 建立 z 資料
      const zValues = xRange.map(x =>
        yRange.map(y => computeZ(x, y))
      );
    
      const data = [{
        type: 'surface',
        x: xRange,
        y: yRange,
        z: zValues,
        colorscale: 'Viridis'
      }];
    
      const layout = {
        title: 'z = sin(x) * cos(y)',
        autosize: true,
        scene: {
          xaxis: { title: 'X 軸' },
          yaxis: { title: 'Y 軸' },
          zaxis: { title: 'Z 軸' }
        }
      };
    
      Plotly.newPlot('plot3d', data, layout);
    </script>
    
    <!-- numeric.js 用來產生 linspace 數列 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js"></script>
    

    操作說明

    函數可替換範例

    說明

    此範例使用 Plotly.js 提供互動式 3D 視覺化,並搭配 numeric.js 輔助產生數值網格。你可以自由變更 computeZ 函數中的內容來畫出任意的三維曲面。



    3D化學結構繪製的JavaScript函式庫

    3Dmol.js

    3Dmol.js 是一個開源且專為瀏覽器設計的 WebGL 化學分子可視化函式庫,可直接在網頁中繪製分子結構。

    <div id="viewer" style="width:400px;height:400px;"></div>
    <script src="https://3dmol.org/build/3Dmol-min.js"></script>
    <script>
      const viewer = $3Dmol.createViewer("viewer", { backgroundColor: "white" });
      viewer.addModel("C1=CC=CC=C1", "smi");  // 苯的 SMILES 結構
      viewer.setStyle({}, {stick: {}, sphere: {scale: 0.3}});
      viewer.zoomTo();
      viewer.render();
    </script>
    

    ChemDoodle Web Components

    ChemDoodle 提供 2D 與 3D 結構繪圖,支援多種化學格式,適用於教學與網頁應用。

    JSmol

    JSmol 是 Jmol 的 JavaScript 版本,適合顯示大分子如蛋白質或晶體結構。

    Mol*

    Mol*(MolStar)是由 RCSB PDB 開發的高階結構視覺化工具,專為生物大分子設計。

    比較表

    函式庫 主要用途 是否開源 是否需授權
    3Dmol.js 通用3D分子視覺化
    ChemDoodle 2D與3D教學、展示 部分
    JSmol 學術研究與教學
    Mol* 蛋白質與生物分子視覺化


    3Dmol.js 顯示苯分子

    使用說明

    此範例使用 3Dmol.js 並採用 XYZ 格式 定義苯分子的原子座標,以正確顯示 3D 分子結構。

    如果使用 SMILES 格式("smi")會出現錯誤 Unknown format: smi,因為該格式在部分 3Dmol.js 版本中未被支援。

    使用步驟

    1. 將以下程式儲存為 benzene.html
    2. 使用本地 HTTP 伺服器(例如 Python 的 python -m http.server)開啟。
    3. 在瀏覽器中進入 http://localhost:8000 檢視結果。

    HTML 程式碼

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>3Dmol.js 渲染苯分子</title>
      <script src="https://3dmol.org/build/3Dmol-min.js"></script>
      <style>
        #viewer {
          width: 600px;
          height: 600px;
          position: relative;
          border: 1px solid #aaa;
        }
      </style>
    </head>
    <body>
    
    <h2>3Dmol.js 苯分子展示 (XYZ 格式)</h2>
    <div id="viewer"></div>
    
    <script>
      document.addEventListener("DOMContentLoaded", function () {
        const viewer = $3Dmol.createViewer("viewer", { backgroundColor: "white" });
    
        const xyzData = `
    12
    benzene
    C       0.0000    1.3968    0.0000
    H       0.0000    2.4903    0.0000
    C      -1.2096    0.6984    0.0000
    H      -2.1471    1.2451    0.0000
    C      -1.2096   -0.6984    0.0000
    H      -2.1471   -1.2451    0.0000
    C       0.0000   -1.3968    0.0000
    H       0.0000   -2.4903    0.0000
    C       1.2096   -0.6984    0.0000
    H       2.1471   -1.2451    0.0000
    C       1.2096    0.6984    0.0000
    H       2.1471    1.2451    0.0000
    `;
    
        viewer.addModel(xyzData, "xyz");
        viewer.setStyle({}, {stick: {}, sphere: {scale: 0.3}});
        viewer.zoomTo();
        viewer.render();
      });
    </script>
    
    </body>
    </html>
    

    注意事項

    3Dmol.js 苯分子展示 (XYZ 格式)



    Google 自訂地圖

    概述

    Google Maps JavaScript API 可讓開發者在網頁中嵌入互動式地圖, 並透過 JavaScript 動態新增標記(Marker)、圖層、文字標籤等自訂元素。 以下範例示範如何顯示地圖並加入自訂的標記。

    ---

    步驟 1:申請 Google Maps API Key

    前往 Google Cloud Console,啟用 Maps JavaScript API, 並建立一組 API 金鑰(API Key)。
    取得後,在載入 script 時附加 ?key=YOUR_API_KEY

    ---

    步驟 2:建立 HTML 結構

    
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Google Map with Custom Tags</title>
      <style>
        #map {
          width: 100%;
          height: 500px;
        }
      </style>
    </head>
    <body>
    
    <h3>我的地圖</h3>
    <div id="map"></div>
    
    <!-- 載入 Google Maps JS API -->
    <script async
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
    </script>
    
    <script>
    function initMap() {
      // 初始化地圖
      const center = { lat: 25.033964, lng: 121.564468 }; // 台北101
      const map = new google.maps.Map(document.getElementById("map"), {
        zoom: 14,
        center: center
      });
    
      // 建立自訂標記
      const myTags = [
        { position: { lat: 25.034, lng: 121.565 }, title: "標記 A", content: "這是 A 點" },
        { position: { lat: 25.036, lng: 121.562 }, title: "標記 B", content: "這是 B 點" },
        { position: { lat: 25.032, lng: 121.568 }, title: "標記 C", content: "這是 C 點" }
      ];
    
      // 建立資訊視窗(InfoWindow)
      const infoWindow = new google.maps.InfoWindow();
    
      // 將標記加到地圖上
      myTags.forEach(tag => {
        const marker = new google.maps.Marker({
          position: tag.position,
          map: map,
          title: tag.title,
          icon: {
            url: "https://maps.google.com/mapfiles/ms/icons/blue-dot.png"
          }
        });
    
        // 點擊顯示資訊
        marker.addListener("click", () => {
          infoWindow.setContent("<b>" + tag.title + "</b><br>" + tag.content);
          infoWindow.open(map, marker);
        });
      });
    }
    </script>
    
    </body>
    </html>
    
    ---

    步驟 3:可擴充功能

    ---

    常用設定

    屬性用途
    center設定地圖初始中心座標。
    zoom地圖縮放等級(1–20)。
    mapTypeId顯示樣式,可為 roadmapsatellitehybridterrain
    icon自訂標記圖示。
    infoWindow顯示點擊標記後的資訊視窗。
    ---

    官方資源



    聲音 in Web

    JavaScript 播放 do re mi 使用 MIDI API

    說明

    要在瀏覽器中播放指定的 MIDI 音色(例如吉他),可使用 Web MIDI API 或更簡單的是使用 Web Audio API 搭配 SoundFont 播放器,如 SoundFont Player 套件 soundfont-player

    範例:用吉他音色播放 Do Re Mi

    
    <script src="https://unpkg.com/[email protected]/dist/soundfont-player.js"></script>
    <button onclick="playDoReMi()">播放 Do Re Mi</button>
    
    <script>
    async function playDoReMi() {
      const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
      const player = await Soundfont.instrument(audioCtx, 'acoustic_guitar_nylon');
    
      const now = audioCtx.currentTime;
      player.play('C4', now);        // Do
      player.play('D4', now + 0.5);  // Re
      player.play('E4', now + 1);    // Mi
    }
    </script>
    

    說明

    支援的吉他音色

    結論

    使用 soundfont-player 搭配 Web Audio API 能輕鬆實現 MIDI 級別的樂器播放功能,不需要安裝任何插件。只要指定音色與音高,即可快速實作如「do re mi」的音階旋律。



    JavaScript 播放 Do Re Mi 使用 AudioContext 合成器

    說明

    如果無法透過外部 SoundFont 播放音色,我們可以直接使用 Web Audio APIOscillatorNode 合成器播放 Do Re Mi,並模擬吉他風格(例如:短促聲音 + 弱音)

    範例程式:內建聲音播放 Do Re Mi

    
    <button onclick="playDoReMi()">播放 Do Re Mi</button>
    
    <script>
    function playTone(frequency, startTime, duration, context) {
      const osc = context.createOscillator();
      const gain = context.createGain();
    
      osc.type = "triangle"; // 接近吉他聲的合成波形,可改為 "square"、"sawtooth"
      osc.frequency.value = frequency;
    
      gain.gain.setValueAtTime(0.2, startTime);
      gain.gain.exponentialRampToValueAtTime(0.001, startTime + duration);
    
      osc.connect(gain);
      gain.connect(context.destination);
    
      osc.start(startTime);
      osc.stop(startTime + duration);
    }
    
    function playDoReMi() {
      const context = new (window.AudioContext || window.webkitAudioContext)();
      const now = context.currentTime;
    
      // Do Re Mi 的頻率 (C4, D4, E4)
      playTone(261.63, now,      0.4, context); // C4
      playTone(293.66, now + 0.5, 0.4, context); // D4
      playTone(329.63, now + 1.0, 0.4, context); // E4
    }
    </script>
    

    特色

    模擬吉他技巧建議

    結論

    使用純 Web Audio API 是最穩定與相容性最高的方式。若有進階需求,可再加上濾波器、回音、或整合 MIDI 音源。



    OscillatorNode 的 type 類型與音色說明

    內建的 osc.type 類型

    osc.type 中文名稱 音色特性 常見模擬樂器
    "sine" 正弦波 最純淨、無諧波 純音、音叉、笛子、電子合成音
    "square" 方波 奇數諧波豐富,音色尖銳 合成器、8-bit 音效、電子鍵盤
    "sawtooth" 鋸齒波 包含所有諧波,音色厚實明亮 弦樂、吉他、銅管模擬
    "triangle" 三角波 只有奇數諧波,聲音較柔和 木管、柔和電吉他聲
    "custom" 自定波形 可自製任意波形 特殊合成音、真實模擬音色

    示範使用方式

    
    const osc = audioContext.createOscillator();
    osc.type = "sawtooth"; // 可改為 "sine", "square", "triangle", "custom"
    osc.frequency.value = 440; // A4
    osc.start();
    

    補充:自定波形

    
    const real = new Float32Array([0, 1, 0.5, 0.25]);
    const imag = new Float32Array(real.length);
    const wave = audioContext.createPeriodicWave(real, imag);
    
    osc.setPeriodicWave(wave);
    osc.type = "custom";
    

    結論

    不同 osc.type 可模擬不同風格的樂器音色。若想模擬吉他建議從 sawtoothtriangle 開始,並搭配 Envelope(音量包絡)、濾波器與回音來細緻調整音質。



    使用 WebAudioFont 播放 Do Re Mi 樂句

    說明

    建議使用WebAudioFont這個開源 JavaScript 庫,它支援超過數千種 MIDI 音色,並包含吉他等樂器音色,音質較佳又易於整合。

    快速範例:播放 Do Re Mi(使用鋼琴或吉他音色)

    
    
    
    
    
    
    

    重點解說

    可替換音色

    總結

    透過 WebAudioFont 結合 Web Audio API,你可以方便地使用真實 MIDI 音色(例如吉他)播放音符,解決純 Oscillator 合成音色單一的問題,同時避免之前 SoundFont 玩家無聲的狀況。




    email: [email protected]
    
    T:0000
    資訊與搜尋 | 回dev首頁
    email: Yan Sa [email protected] Line: 阿央
    電話: 02-27566655 ,03-5924828
    阿央
    泱泱科技
    捷昱科技泱泱企業