2024年7月22日 星期一

OpenAI Whisper : 英文音檔變中文字幕

2024年7月22日 星期一

前幾天利用 Faster Whisper 轉 VOA Learning Englishhttps://learningenglish.voanews.com/ ) 的 MP3 音檔為 SRT 字幕檔時,因為忘了設定語音的語音代碼,就這麼用了前一次使用的中文的代碼「zh」,哈!也太奇妙了!Whisper 真的給了我中文的字幕吔!為了證明自己不是在作夢,又重新用了另一個英文的音檔,一樣的,語言代碼使用「zh」,重新玩一次,輸出結果還是中文!語言代碼改用「ja」,就變成日文了(圖1),不過日文似乎比較不穩定,常會出現英文的。

[圖1]  英文音檔輸出日文的字幕檔

下面來以 July 21, 2024 這篇「Evidence of ‘Rotten Egg’ Gas Found on Jupiter-like Exoplanet」為例,簡單地記錄一下,怎麼將 VOA Learning English 的音檔轉為中文字幕檔。

先開啟 VOA 的頁面,打開底下這個網址:

[圖2] 找出 VOA 文章音檔下載網址

如 [圖2] 在文章的語音播放器右下角有一個「Direct link」,點一下即可出現 MP3 的下載清單,對準其中一個按滑鼠右鍵,並選取「複製連結網址」。接下來就可以將網址貼到我之前設計的 Faster Whisper 或是 OpenAI Whisper 的 Google Colab 筆記本中了。

以 Faster Whisper 為例,如 [圖3] ,

[圖3] Faster Whisper 的設定

進行幾項設定:

  • url : 「聲音檔的來源」貼上由 VOA Learning English 複製來的 MP3 網址。
  • lang : 語音的語言代碼如果想要英文的字幕檔,就選「en」;想要中文的,就選「zh」。
  • outputFormat : 輸出格式選「srt」。
  • modelType : 「使用哪一種辨識模型」選取「large-v3」。
  • initial_prompt : 「提示語」如果是想輸出繁體中文,就選「以下是繁體中文的句子」。
都設定好,就可以按左側的執行鈕(三角形的播放圖示)。按完就等候結果了。

[圖4] 語言代碼選「zh」就輸出中文字幕檔

[圖5] 語言代碼選「en」就輸出英文字幕檔

看看上面 [圖4] 的語言代碼選「zh」,最後輸出中文的字幕檔;[圖5] 的語言代碼選「en」,最後輸出英文的字幕檔。它們都是用這個 MP3 音檔來進行語音辨識的:

OpenAI Whisper 明明只支援將其它語言語音轉文字以後,翻譯為英文,卻可以這樣玩;查了一下,有人說這可能是 OpenAI Whisper 的 bug,但是這功能也太好用了,希望不會從專案中移除。

接下來,我想試著看看能不能將兩種不同語言的字幕檔合而為一,這樣子搭配 HTML5 FUN Audio Player 來使用:

看看 OpenAI Whisper 和 Bing Translator 誰翻譯得好 ^_^

相關連結




2024年7月13日 星期六

HTML5 FUN : PLAYER 增強聽、讀能力

2024年7月13日 星期六

六月底提到同事送小孩一套英文書 (詳見:雄:Python: BeautifulSoup 與 querySelectorAll),我將書附的音檔下載,並以 OpenAI Whisper 將音檔轉出字幕檔,接下來就啟動了一個小專案,想要做一個簡易的聽、讀小工具,可以:

  • 載入影音檔案播放。
  • 載入並顯示字幕檔的內容,按哪一句,就能跳到那一句播放影音。
  • 選定語言後,將文字內容進行批次翻譯;並能隨意地隱藏或顯示譯文。
  • 播放影音時,可以自訂播放的速度。
  • 遇到生難字詞時,可以標記後查字典;或是標記後轉到筆記中。

經過幾天的努力,這個 HTML5 FUN PLAYER 大致完成了;前述的功能,只有最後一項沒做,因為後來在 iPad 上測試時,發現當我們將文字標記好後,iOS 就內建查字典、轉貼到備忘錄或其它工具的功能了,何必再自己「造輪子」。

開啟工具



使用說明

目前 HTML5 FUN PLAYER 除了可以載入本機的 SRT 字幕檔與影音檔案,也可以使用有字幕的 Youtube 影片,只要貼 YouTube 的影片網址,會自動列出可用的字幕語言清單供選取。

[圖1] 加入 YouTube 影片的流程

當字幕檔案及影音檔案都載入以後,每一句話的左側會有一個小三角形,按一下三角形,即可跳到該句播放;想暫停,只要按一下字句右側任何一處空白的地方,即可停止播放。

影片示範

Q & A

  • Q: 字幕檔可以使用什麼格式的?
    • A : 目前使用的字幕檔是 SRT 格式。
  • Q: 影音檔支援哪些格式?
    • A : 目前支援的影音格式有 .mp3 .mp4 .mkv .mov .avi .webm
  • Q: 新增媒材時,字幕檔跟影音檔可以一起選取或拖曳嗎?
    • A: 可以的,選取檔案與拖曳檔案都有支援多檔案,但是注意,只能一個影音檔,一個字幕檔,不然只會使用最後一個同類型的檔案。
  • Q: 只有音檔或是影片檔,如何自製字幕檔?
  • Q : Youtube 的影片沒有字幕檔,可以自製嗎?
  • Q: 翻譯是使用哪一個工具產生的?
    • A: 本工具是使用 Microsoft 的 Bing 翻譯來完成批次翻譯的工作。
  • Q : 可以自動載入影音嗎?
    • A: 如果在本工具的網址後上加上「 ?v=影音的網址 」 ,這樣子在程式啟動時,即可自動開啟該網址;另一個方法是將影音的網址加在字幕檔裡面,載入字幕檔案以後,會順便載入影音。
  • Q : 在電腦上播放影音有快速按鍵嗎?
    • A: 在電腦中操作,除了用滑鼠,也可以使用鍵盤的按鍵
      • Esc : 播放 / 暫停。
      • F1 : 重播該句,播上一句(連按兩次)。
      • F2 : 播放下一句。

相關連結

更新記錄

  • 2024.07.26 如果字幕檔中帶有影音的網址,字幕載入完畢會自動載入該影音;修正顯示/隱藏翻譯時,內容無法保持於正在看的那一段,需要手動捲回定點的問題。
  • 2024.07.25 可使用鍵盤的 Esc 控制播放/暫停、F1 回播/跳到前一句、F2 跳到下一句;調整速度的區塊新增跳到前一句、跳到下一句的按鈕;在網址中加入 v=xxx ,xxx 可以是 YouTube 的影片代碼,或是影片網址,即可自動載入該影音。
  • 2024.07.24 YouTube 的影片如果有一個以上的字幕,可以選用第二字幕。
  • 2024.07.22 播放鈕及翻譯加上圓形進度狀態顯示;無法翻譯時,顯示警示的訊息;YT輸入區如果是其它影音的網址,會試著加入播放;只有影音無字幕時,亦可顯示播放進度;影音播放完會改變播放鈕的狀態;速度改變控制區塊可自改拖曳換位置;影片觀看區域如果超出邊框,會自動修正位置。
  • 2024.07.15 新增查字典的按鈕,將要查詢的文字反白以後,按下想使用的字典,即可前往該字典的頁面。
  • 2024.07.14 影片支援顯示第一個翻譯的字幕,按一下邊框可以放大/縮小,拖曳邊框可以移動位置。
  • 2024.07.01 初稿

HTML5 FUN::PLAYER

2024年7月10日 星期三

以 MSYS2 在 Windows 構建 Translate Shell 的環境

2024年7月10日 星期三

上個月底幫小孩抓了英文套書的所有音檔,為了方便檢索,利用 OpenAI Whisper 轉好了字幕檔,接著又想弄個雙言的字幕檔,連聽、讀的小工具都寫好了;哈!像滾雪球一樣,愈玩愈大。

在尋找能批次翻譯的工具時,發現了這個 Translate Shell

看中它的原因有兩個,它可以選用 Google 或是 Bing 來進行翻譯,還能將文字轉合成語音(TTS)後的檔案直接儲存。Google TTS 儲存成 MP3 之前玩過,Bing TTS 轉存以前玩過較複雜的,但 Translate Shell 的看起來較簡單。但是的但是,試過才發現 Translate Shell 中的 Bing TTS 抓取程序已經不能用了。不過!研究過以後,我已經知道目前 Bing TTS 的擷取程序了,而且也以 Python 跟 JavaScript 實作過,要轉為 Traslate Shell 的 gawk 語法,也不是難事。

針對 Bing TTS 的程序修正過以後的版本放在這裡:

Translate Shell 滿特別的地方是它使用 GNU Bash 的環境,執行 GNU Awk 的指令來完成翻譯或是抓取 TTS 合成語音。這兩樣如果是在 Unix like 中,要安裝及使用,實在太容易了。但是在我的 Windows 7 中,雖然有 bash ,也有 gawk,但試了好幾天,總是看得到誤錯訊息,而看不見翻譯結果。本來已經放棄 Windows,改到 Mac OS X 、 Linux Mint 跟 Google Colab 中去測試我修改好的 Translate Shell 了。重新再找 Windows 7 的解決方案時,看到了一個對我來說很新鮮的東西 「MYSYS2」 :

它可以在 Windows 建構一個誇平臺的開放環境,不但有我需要玩 Translate Shell 的環境,安裝完,佔的磁碟空間也不大。那有沒有支援 Windows 7 呢?幸好!舊版的是可以安裝的。詳細說明在官網中:

支援 Windows 7 的最後版本在這裡下載:

安裝完,測試了一下,在 MSYS2 中可以正常執行 Translate Shell ,這樣子我修改程式就不用在不同系統中切來切去了。

在 Windows 中想編譯 Translate Shell 可以下這樣的指令:

gawk -f build.awk build -target=bash -type=release

成功的話,可以在 build 目錄中找到 trans 這個檔案。

在 MSYS2 中執行 Translate Shell

Translate Shell 以這樣的指令可以製作中文字串的合成語音:

trans -e bing -b -speak -no-translate -no-play -download-audio-as tts.mp3 zh-TW:en "我現在要來測試一下語音合成的功能,將語音儲存為MP3檔案"

參數記錄一下:

  • -e bing : 使用 Bing 來進行翻譯或合成語音(不指定時,使用 Google)。
  • -b : 使用精簡模式,顯示較少的結果。
  • -speak : 說出合成原文的語音;如果想要播放的是翻譯的語音,就用 -p 的參數。
  • -no-translate : 只合成語音,不翻譯。
  • -no-play : 不播放語音。
  • -download-audio-as : 將語音儲存為指定的檔名(本例是儲存為 tts.mp3)。
  • zh-TW:en 原文為繁體中文,翻譯為英文(雖然本例不進行翻譯)。
後續再來分享 HTML5 支援多語字幕的 MP3 聽讀小工具,及以 Python 批次呼叫翻譯、下載合成語音的小工具。

相關連結


2024年7月8日 星期一

HTML TABLE 與 DIV TABLE 貼到文件中比較

2024年7月8日 星期一

前幾天在幫 Google 日曆轉簡明行事曆加上「複製」的功能,可以將製作好的行事曆複製到剪貼簿中以後,再貼到 Google 文件中編輯行事曆的內容,結果發現表格全亂了套。主要是原來的表格是使用 <DIV> 的語法,再搭配 CSS diplay: table 的樣式所產生的,沒想到眼中所見的表格,複製到剪貼簿又是另一回事了。只好再乖乖地將語法通通再改回 HTML <TABLE> 的語法了。

[圖1] 由 Google 日曆轉換的行事曆

[圖2] DIV TABLE 貼到 Google 文件的樣子

來做一下小實驗,底下同樣的資料內容,一個用 DIV 製作看起來像表格的表格(DIV Table),一個用真正的表格 (TABLE),看它們分別複製後,貼到 Google 文件中,有沒有差別?


DIV TABLE

A
B
C
1
2
3

HTML TABLE

A B C
1 2 3

相關連結


2024年7月4日 星期四

JavaScript : 擷取 Google 日曆製作簡明行事曆

2024年7月4日 星期四

回想自己班級網站的經營歷程, 2007年起的班級網頁就改放到 Googloe Blogger。2009年那一屆更精進一些,利用 Blogger 可以自訂發布時間,時間到了,文章自動發布,用這個機置,前一天就將聯絡簿的內容打到新文章中,然後定時張貼,有學生很認真地發現了這個機置,居然一大早就上網看內容,人還沒到學校,回家功課的項都抄完了;另一個則是班級行事曆是使用 Google 日曆,在班級網站首頁中,以程式抓取日曆內容,並顯示最近的行事內容。

那幾年用的是類似這樣的網址來抓取公開的日曆內容:

http://www.google.com/calendar/feeds/日曆的ID/public/full?orderby=starttime&sortorder=ascending&alt=json-in-script&callback=listEvents&start-min=2009-01-01T00:00:00+08:00&start-max=2024-07-04T00:00:00+08:00

這兩天試了一下, 這個格式的網址已經不能用了。那有沒有替代的呢?

看到網路中的教學,大多是得使用 API key ,然後去呼叫 API。既然是公開的日曆,幹嘛還需要 API key?

觀察了一下網路中那些公開的 Google 日曆,其實它在擷取資料時,是用類似這樣的網址:

https://clients6.google.com/calendar/v3/calendars/日曆的ID/events?calendarId=日曆的ID&singleEvents=true&eventTypes=default&eventTypes=focusTime&eventTypes=outOfOffice&timeZone=Asia%2FTaipei&maxAttendees=1&maxResults=最多幾則&sanitizeHtml=true&timeMin=編碼過的開始日期時間&timeMax=編碼過的結束日期時間&key=AIzaSyBNlYH01_9Hc5S1J9vuFmu2nUqBZJNAXxs&%24unique=gc456

如果 Google 日曆是「有設為公開」的,將網址中紅色的部份置換掉,就能抓到 JSON 格式的日曆資料,剩下的,就看要輸出什麼欄位,輸出成什麼樣子了。

來試一下,直接利用 Google 日曆,輸入起始日期、顯示週數,就能製作簡明行事曆。(按這裡套用2012年範例的設定)



操作示範的影片


簡明行事曆


2024年6月24日 星期一

Python: BeautifulSoup 與 querySelectorAll

2024年6月24日 星期一

上週接收了好心同事一整套的英文書 I Wonder Why (Kingfisher 2004版)。查了一下,新版的在書上有附語音檔的 QR code,跟小孩子說,沒關係,只要找到一個連結,應該就都能找出來了。

「將~將~」,真的找到了:

在這個連結的頁面中,除了該冊每兩頁有音檔以外,也有其它冊的連結,這樣子真的是一個連結全部搞定了。

音檔可以下載到載具中,這樣子就可以離線使用;但是要一個個手動按下載嗎?二十本書,應該會按到手廢掉了。

分析了一下網頁的原始碼,果然很結構化,這樣子要找出音檔的連結就方便多了。

剛好前幾天有示範 JavaScript 的 querySelector 跟 querySelectorAll 的應用給小孩子看,順便再複習一下,如何在頁面中找出網址。在瀏覽器開啟前述頁面,然後在開發人員工具中的 Console ,使用這樣的語法:

mp3 = '';
var links = document.querySelectorAll('.synopsis-wrapper li a');
for(var i=0; i<links.length; i++) {
  url = links[i].href;
  res = await fetch(url);
  html = await res.text();
  var parser = new DOMParser();
  doc = parser.parseFromString(html, 'text/html');
  doc.querySelectorAll('source:not([src*="_extras"])').forEach(s=> mp3+=s.src+'\n');
}
console.log(mp3);

最後會將所有書的 mp3 音檔連結,一行行合在一起呈現。

看來網站是有防跨域擷取的,所以使用瀏覽器的 fetch 抓網頁,只能在 I Wonder Why 的頁面中才能成功執行。

由音檔的網址來分析,其實主要分為兩種:

  • insides
  • extras

非「extras」的才是我要下載的。為什麼不說是「insides」的才是我要下載的?

哈!本來我是用:

querySelectorAll('source[src*="insides.mp3"]')

中括號的 Attribute selectors 限定 src 的內容帶有 insides 的才留著,結果有兩本書的內容就解析不到音檔的網址。人工查了一下,才發現一個是會在 .mp3 前多了 new,另一個則是連 insides 都沒有。所以最後使用了 not([src*="_extras"]) ,這樣一來,非「extras」的條件,簡化了語法,不然又要打很多字來設條件了。

擷取出來的音檔網址要怎麼下載檔案?

最方便的就是使用 wget,它有提供「-i」的參數,可以讀入存有網址清單的純文字檔,然後一個個的下載回來。

如果把這麼多檔案放在一個資料夾裡面,要使用實在不方便,所以決定用 Python 來試試。如果在 Google Colab 中執行,分析完音檔的網址,直接就儲存到 Google Drive 中,這樣子在行動載具,只要由 Google Drive 中開啟來用;或是乾脆整個下載到載具儲存更好。

在 Python 中想要使用類似 JavaScript DOMParser + querySelectorAll 的功能,第一個想到的就是 BeautifulSoup。BeautifulSoup 的 select 語法和 querySelectorAll 一樣,實在是太棒了。

底下將整個語法貼在下面:

import re
import os
import requests
import urllib.request
from bs4 import BeautifulSoup

rootFolder = 'drive/MyDrive/00-i-wonder-why'

menuPageUrl = 'https://audio.panmacmillan.com/i-wonder-why-snakes'
html = requests.get(menuPageUrl).text
soup = BeautifulSoup(html, 'html.parser')
links = soup.select('.synopsis-wrapper li a')

for a in links:
  url = a.get('href')
  html = requests.get(url).text
  soup = BeautifulSoup(html, 'html.parser')
  title = re.findall(r'i-wonder-why-(.*)$', url)[0]
  print(title)
  source = soup.select('source:not([src*="_extras.mp3"])')
  print(len(source))
  folder = f"{rootFolder}/{title}"
  if not os.path.exists(folder):
    os.makedirs(folder)
  list_filename = f'{folder}/00-list.txt'
  list_txt = ''
  for s in source:
    mp3URL = s.get('src')
    pp = re.findall(r"pp(\d+)-(\d+)[^\.]*\.mp3", mp3URL)
    filename = title
    for n in pp[0]:
      filename +=  '-' + n.rjust(2, '0')
    filename += '.mp3'
    list_txt += f'{filename}\r\n'
    #print(mp3URL)
    filename = f"{folder}/{filename}"
    urllib.request.urlretrieve(mp3URL, filename)
  if list_txt != '':
    f = open(list_filename, 'w')
    f.write(list_txt)
    f.close()

音檔下載後,將檔案名稱改得簡單一點,並儲存到各冊自己的資料夾中;也順便將音檔的清單存入各資料夾中的「00-list.txt」文字檔中。

「00-list.txt」是我為下一階段所做的準備。為了方便聽音檔時可以快速檢索,我使用 OpenAI Whisper ( 後來改用 Faster Whipser ) ,將音檔進行語音辨識,並輸出為字幕檔,因為一句句都帶有時間截記,要快速重聽某一句就方便多了。哈!我之前分享過的 OpenAI Whiper ,跟 Faster Whisper ,經過我的打造,都支援由文字檔中讀取音檔清單,然後也可以自行設定輸出的資料夾,輸入、輸出都設定到 Google Drive 我放 I Wonder Why 的音檔資料,這樣子就可以「一條龍」了!兩個工具可以參考之前的文章:

為什麼後來改用 Faster Whisper  ? 主要是 OpenAI Whisper 比較耗資源,解譯完一冊書的音檔,第二冊進行到一半,就被重置,這實在太令人氣結了。

不過,用著用著,才發現自己寫的程序有一些小臭蟲,前面的 「00-list.txt」中放的是只有音檔的檔案,因為不是絕對路徑,一直出現了找不到音檔的訊息,並沒有進行語音辨識;另外,輸出的資料夾如果沒有先建立好,也不會照設定儲存到雲端硬碟中,針對這些問題,會再更新到公開的版本中。

有了音檔,有了字幕檔,目前我們使用 oTranscribe 在 iPad 中聽語音 :

如果遇到需要查中文的,就直接將字詞選取以後,使用 iOS 內建的字典來看,整體看起來,還算可以。

字幕檔變雙語?試了一下,也滿好玩的,一行英文,一行中文,利用 Microsoft+Copilot ChatGPT 就能製作了,目前使用這樣的 prompt

translate the following subtitles text to traditional Chinese , treat as one continuous text, keep the source format and append Chinese to the next line of English :

ChatGPT 3.5

Translate the English subtitles text into traditional Chinese, add Chinese after the line of English. the subtitles is:

產生的雙語字幕檔,還需要利用 Regular Expression 處理一下,不過,一道指令就可以完成了。

還在構思是否要來寫個 HTML5 的閱讀小工具,可以比 oTranscribe 更方便的聽讀、查閱。

相關連結




2024年6月20日 星期四

HTML5 : PARTDLE : 迴文的處理

2024年6月20日 星期四

HTML5 FUN PARTDLE 是針對語詞設計的部件兜一兜遊戲,看到被拆解後的部件,想到它們屬於什麼字、什麼詞,然後再將部件拖曳到方框中,都兜完了,再進行答案核對。

像 [圖1] 這一題,答案會什麼呢?

[圖1] 迴文類型的題目

有的人想到是「出發」,有的人則會拼出「發出」,萬一選擇的語詞和題庫的答案不同,程式會怎麼處理呢?

目前最新的版本,PARTDLE 檢查使用者送出的答案,如果發現格子內的字,部件都對了,但是順序和題庫的不同,就會如 [圖2] 試著查詢我由教育部《重編國語辭典修訂本》下載的字詞庫:

[圖2] 與題庫的答案不同就查字典

如果在找得到的語詞,一樣算過關。

[圖3] 有多個答案的過關畫面

有兩個答案時,《教育百科》的詞條查詢連結也會像 [圖3] 出現兩個。

想玩玩看都是回文的題目,可以按底下的按鈕進入 PARTDLE :

按這裡玩~正的答~倒著答的迴文 PARTDLE

題庫連結:

相關連結


2024年6月17日 星期一

JavaScript : 增加 SVG path 的觸控感應範圍

2024年6月17日 星期一

最近很認真的研究 SVG 的圖形,原本是在做筆順練習改版的前置作業,結果寫了以 SVG 圖形元件為主的小遊戲 HTML5 FUN PARTDLE。初版的 PARTDLE 遇到在平板上拖曳 SVG path 繪製的國字部件,有時移動會很遲鈍的情形,也可以說是點不到部件,尤其是面積較小的部件;另外像「口」這種「中空」的形狀,有的人習慣按著中央後開始拖曳,但是因為中央空白的部分並是不屬於「口」的 path,當然就「感應」不到了。

「太小」和「中空」的 SVG 圖形元件,怎麼增加它們的「感應區」呢?

一開始我是以國字的「部件」為單位,依部件的大小,在底層加一個填滿且透明的矩形,這樣子,隨便點,部件都會被感應到。不過,針對部件大小來加入的矩形背景也有新的問題產生,像「返」的「辶」部,看起來是在字的左下角而已,如果取部件的矩形範圍,幾乎是整個字的大小了,如果又剛好是先被點選了,它右上角的小部件,可能因位於下層,就會被遮掩而無法點選。又比如像「回」,中央的小部件「口」,也可能被大的遮蔽。

[圖1] 是將字以「部件」為單位,加上「矩形」背景的結果(暫時以黃色顯示):

[圖1] 在部件底層加上矩形背景

為了減少範圍較大的 path 去遮蔽較小的,第一個想法是不要使用矩形來畫背景,改用橢圓形;另外,PARTDLE 的字是用教育部筆順網的筆順資料,圖形的基本單位是「筆畫」,所以如果加背景時,改以「筆畫」為基本單位,這樣子,像「辶」部,只會在字的左下角加上背景,對字右上方其它部位的影響,就會減到最小。

[圖2] 是將字以「筆畫」為單位,加上「橢圓」背景的結果(暫時以黃色顯示):

[圖2] 在筆畫的底層加上橢圓形背景

如果看靜態的圖片及前述的說明不太能理解,底下利用「啊」這個字的實際操作來體會一下差異。測試時可以試著在「口」的中央拖曳看看,加了背景,再試著拖曳看看。

請按底下四個功能鈕的其中一個,它會先載入 SVG 圖檔,接著就可以拖曳「啊」的各部件來測試感應區到底有什麼差別。


[請選擇上方按鈕載入字]

相關連結

2024年6月15日 星期六

HTML5 : 112-2 國語 PARTDLE 遊戲集

2024年6月15日 星期六

底下是以112學年度下學期國小國語生詞當題庫的的 HTML5 FUN PARTDLE 遊戲。設定「版本」或「年級」會出現遊戲的網址跟 QR code,按一下網址可以將網址複製到剪貼簿中,按一下 QR code 的圖案則可以在新的分頁進入遊戲。

PARTDLE 支援多點觸控,如果在平板或是有觸控功能的螢幕上操作,可以多人合作,一起破關哦!比較一下,或許可以「雙手互搏」,具有「左右開弓」的能人異士,答題的速度會飛快。

底下是選單的截圖:


如果想設計自己的 PARTDLE 遊戲,可以參考遊戲主頁「雄:HTML5 FUN : PARTDLE 兜一兜」中的說明。

題庫檔案

本頁面中的 PARTDLE 題庫內容集中在一個 Google 試算表中,可以按底下的連結看原始內容:

回報問題

由於部件設定有六千多筆,都是我一個個手動輸入的,難免有錯誤,所以如果遇到「兜一兜」完,明明答案應該是對的,卻無法過關,請在本篇文章最下方的留言區輸入無法過關的語詞,有空我再來檢查是哪裡有問題。

版權聲明

本程式所使用的筆順資料來自:

語詞查詢連結連至:

相關連結


2024年6月13日 星期四

HTML5 FUN : PARTDLE 兜一兜

2024年6月13日 星期四

HTML5 FUN 的筆順練習使用了教育部「國字標準字體筆順學習網」的筆順資料,再結合 HTML5 FUN 的部件設定,除了可以練習筆順,也能利用部件來增進學習的效能。2024年5月參照數位發展部的「CNS11643中文標準交換碼全字庫」,重新整理了 HTML5 FUN 的部件設定,除了讓部件規準化,也發展了一個新的遊戲叫「PARTDLE」,它載入語詞的題庫以後,會將字拆解為部件,玩家的目標就是在看到被打亂的部件以後,將它們「兜一兜」,還原為原來的詞語,送出答案核對,答對了,就繼續下一題。除了使用拖曳的方式來進行字詞的「兜一兜」,也可以使用「語音輸入」的方式來說出答案。答對了,也提供教部雲教育百科詞條查詢的連結,方便查看詞語的用法。

開始玩

想要來玩玩 HTML5 FUN 的「PARTDLE」,就按一下底下的紅色啟動鈕。


試試其它題目

使用自訂的題庫

PARTDLE 除了玩預設的題庫,也可以使用自己 Google 試算表中的題庫。方法如下:

  1. 在 Google 試算表的第一個工作表的「A」欄中,依序往下方填入題目,一格一個中文詞語。(也可以輸入在B欄或其它欄中,後面的步驟可自行選取遊戲要用哪一欄)
  2. 將試算表「共用」為「任何知道這個連結的網際網路使用者都能查看」。
  3. 複製共用網址。

完成前面三個準備程序,接下來,

  • 將複製好的試算表共用網址,貼到底下的遊戲網址產生器,
  • 按 [擷取資料試算表] 的按鈕,即可預覽前幾筆資料。
  • 點選要使用的欄位。
  • 按 [送出參數並製作網址] 

完成後即可測試自訂的題庫:

  • 按一下 QR code 的圖案可以直接開啟遊戲頁面來玩。
  • QR code 可以用行動載具掃瞄。
  • 網址按一下可以將遊戲網址複製到剪貼簿中。

參數設定

雲端硬碟試算表 [共用連結網址]
【擷取試算表資料】

Partdle 會載入試算表中指定欄位的題目,所以如果題目很多,建議可以分割,放在同一個試算表中,但使用不同的欄位;最後在製作時,選取不同的欄位,即可產生不同的遊戲網址及 QR code 。

相關影片

報問題

由於部件設定有六千多筆,都是我一個個手動輸入的,難免有錯誤,所以如果遇到「兜一兜」完,明明答案應該是對的,卻無法過關,請在本篇文章最下方的留言區輸入無法過關的語詞,有空我再來檢查是哪裡有問題。

版權聲明

本程式所使用的筆順資料來自:

語詞查詢連結連至:

相關連結

更新記錄

  • 2024.06.25 加入檢查部件擺放位置的功能,目前以答案區方框的十分之一大小為容許值,檢查時用該字最大的部件來當參考點;迴文查字典的方式改為在取得題目時,即同步查出可用的答案有哪些,避免查字典等待的時間太久。
  • 2024.06.20 如果每字的部件都拼對,詞不對,試著檢查是否為《重編國語辭典修訂本》收錄的詞,找到的話,就算對,並出現兩種語詞的教育百科搜尋連結;解決 iOS 舊版因為音效載入及部件大小、位置計算問題,而無法玩的問題。
  • 2024.06.18 加入「稍後作答」的按鈕,遇到有問題或是答不出來的題目,可將該題暫時放到題庫的最後,先做下一題;將原本隱藏的「部件重排」按鈕改為預設顯示。
  • 2024.06.16 載入筆順時,以打亂順序的方式載入,避免可以由出現的順序看出答案;題目先以語詞部件總數排序,部件少的先玩,跨越不同總數時,出現升級的訊息,並加1000點。
  • 2024.06.15 如果下載不到筆順資料的字,會以全字一個部件的方式呈現。
  • 2024.06.14 在部件中心加一個幾乎全透明的小圓當背景,提高被按到的機率;支援多點觸控,可以多人一起玩;自訂題庫提供資料預覽畫面,可以選取想要使用的欄位。
  • 2024.06.13 發布。


2024年6月11日 星期二

JavaScript : 讀取 Google 試算表的內容

2024年6月11日 星期二

這幾天在寫一個新的遊戲,自訂的題庫打算直接讀取 Google 試算表的內容,所以重新研究了一下如何利用 JavaScript 擷取試算表的資料。時間投入了,又有新的發現,去年玩「雄: HTML5 FUN:自製遊戲啟動器」用過的東西,感覺好像忘了不少,還是把一些關鍵的東西記錄一下比較保險。

擷取試算表資料的網址

Google 試算表只要在共用的設定中,將「一般存取權」中,「知道連結的任何人」設為「檢視者」,就會變成「任何知道這個連結的網際網路使用者都能查看」的權限。以此共用方式,我們就可以利用 JavaScript 來擷取試算表中的某一個工作表。用類似這樣的網址來擷取:

https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/gviz/tq?tqx=out:json&tq

網址中,{SPREADSHEET_ID} 是 Google 試算表的 ID,例如我月來當成語題庫的試算表,它的共用網址為:

https://docs.google.com/spreadsheets/d/1kBueULlojPOH9E3EZYEUcUAv1HfJm_wULQT1hT2m1nM/edit?usp=sharing

{SPREADSHEET_ID} 就是在「/d/」和「/edit?」之間那一長串藍色粗體的字串。

想要直接擷取試算表的資料,就組合為這樣的網址:

https://docs.google.com/spreadsheets/d/1kBueULlojPOH9E3EZYEUcUAv1HfJm_wULQT1hT2m1nM/gviz/tq?tqx=out:json&tq

試算表擷取的資料分析

如果我們以前面所述的網址,可以下載試算表中最左側,第一個工作表的資料。

內容會類似這樣:

/*O_o*/
google.visualization.Query.setResponse({..........});

觀察一下,第一行的 /*O_o*/ ,看起來是不是就是 JavaScript 的註解;

而 google.visualization.Query.setResponse( ) ,是不是就是一個 function ?

我們要的資料是在小括號中的 {..........}

是的!它是 JSON 的格式,也就是試算表的資料會被當成一個參數,傳給名為 google.visualization.Query.setResponse 的 function。

以字串處理來取得資料

如果我們是用檔案下載的方式來取得,回傳的會是字串(假設給了 data 變數),這樣子我們可以用這樣的指令來取得文字內容:

data.substring(47, data.length - 2)

從第 47 的大括號「{」,取子字串到倒數第 3 字的大括號「}」,因為結果是文字型態,所以還得再利用 JSON.parse 來將字串型轉換為物件,整合起來的指令為:

JSON.parse( data.substring(47, data.length - 2) )

以 JSONP 來取得資料

前面分析過,我們擷取的資料,其實內容就是 JavaScript 的指令,如果將內容指定給一個網頁面頁中的 script ,接收完資料,瀏覽器會呼叫「google.visualization.Query.setResponse」,並將試算表的資料傳給它,因此我是利用 JSONP 呼叫 callback 來取得並處理資料,先寫了個 callback ,再利用下面幾行來讓它們建立關係:

if(typeof(google)=='undefined') google = {};
if(typeof(google['visualization'])=='undefined') google['visualization'] = {};
if(typeof(google['visualization']['Query'])=='undefined') google['visualization']['Query'] = {};
google['visualization']['Query']['setResponse'] = callback;

牛刀小試

底下來做個小實驗,可以在 Google 雲端硬碟中建立一個試算表,輸入一些資料以後,將該檔案設定為「任何知道這個連結的網際網路使用者都能查看」的共用方式,並複製連結,貼到底下的輸入區後按「擷取」鈕,看看能不能抓到資料。


試算表共用網址:

轉換後的網址:

試算表的資料:    縮排:

 

擷取指定的工作表

一個試算表中,可以有多個工作表,如果照前面格式,只修改了 {SPREADSHEET_ID} 而成的網址,它是抓取試算表最左側的工作表,想要擷取別的工作表,就需要利用 sheet 或是 gid 的參數來指定。這兩個參數如果同時放到網址中,我的操作經驗,是看哪一個放在前面,就優先使用該參數。

使用 sheet 參數來擷取指定名稱 {SHEET_NAME} 的工作表資料:

https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/gviz/tq?tqx=out:json&tq&sheet={SHEET_NAME}

例如我前面的成語題庫試算表有「工作表2」,我可以用這樣的網址來擷取資料:

https://docs.google.com/spreadsheets/d/1kBueULlojPOH9E3EZYEUcUAv1HfJm_wULQT1hT2m1nM/gviz/tq?tqx=out:json&tq&sheet=工作表2

使用 gid 參數來擷取指定代號{SHEET_ID} 的工作表資料:

https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/gviz/tq?tqx=out:json&tq&gid={SHEET_ID}

例如當我在編輯前面成語題庫試算表「工作表2」時,它的網址是:

https://docs.google.com/spreadsheets/d/1kBueULlojPOH9E3EZYEUcUAv1HfJm_wULQT1hT2m1nM/edit#gid=543013940

網址中有 gid=543013940 ,所以 543013940 就是{SHEET_ID},我可以用這樣的網址來指定要擷取資料的工作表:

https://docs.google.com/spreadsheets/d/1kBueULlojPOH9E3EZYEUcUAv1HfJm_wULQT1hT2m1nM/gviz/tq?tqx=out:json&tq&gid=543013940

以這個試算表來說,因為「sheet=工作表2」和「gid=543013940」指的都是同一個工作表,所以抓到的資料都是一樣的。

擷取 SQL 指令篩選過的資料

在前面擷取資料的網址中,是不是都有一個參數「tq」?

如果想要先以 SQL 語篩選試算表中的資料,再擷取,可以用 tq={SQL} 指令的方式來進行篩選。預設不指定。例如我只想找出 B 欄成語有「一」這個字的,可以用這樣的語法:

select * where B like '%一%'

例如我只想要回傳 C 欄的資料就好,就用這樣的語法:

select B

例如只想回傳前 10 筆資料,就用這樣的語法:

select * limit 10

此部份有興趣可以再研究。

手動設定「標題」有幾列

在 Google 試算表回傳的資料中有一個 parsedNumHeaders ,它會指出有多少列資料是「標題」,資料會被放到 cols 各欄的 label 中,而 rows 中就少了那幾列。

我們可以在請求資料的網址中利用 headers 的參數來設定有多少資料要當「標題」。

所以如果有使用 gid 參數,又使用 headers 參數,就會變成類似這樣網址:

https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/gviz/tq?tqx=out:json&tq&gid={SHEET_ID}&header={HEADERS} 

 上面的 {HEADERS} 置換成想設定的數字即可。

進階測試版


試算表共用網址:

工作表名稱:

工作表識別碼(gid):

SQL:

轉換後的網址:

試算表的資料:    縮排:

 

資料內容

試算表傳回的資料,幾個重要的項目:

  • status : 如果內容是 "ok",表示有擷取到資料。
  • table
    • cols
      • id : 欄位的代碼 A、B、C...。
      • label : 如果 parsedNumHeaders = 1,內容就是最上面一列的內容;如果 parsedNumHeaders = 0,label 會是空字串。
    • rows : 一列列儲存格的資料,要注意 parsedNumHeaders 的值,不然會有少幾列的情形。
    • parsedNumHeaders : 是否有取某幾列當欄位的「標題」,當它不等於 0 時,rows 會少那幾列內容,因為拿去放到 cols 中了,這一部份要注意。

相關連結


 
雄::gsyan © 2009. Design by Pocket