[n8n][Gemini] 如何用 Gemini 2.5 來抓取 YouTube 字幕並且變成 n8n 自動流程

LINE 2025-08-08 23.29.29

前言

抓取 YouTube 字幕一直是很痛苦的事情,除了我之前有寫過文章來分享相關方法外。後來都會發現 Google 會有各種限制:

  • LangChain API -> 直接檔。
  • Transcript API -> 一直被阻擋,需要花錢去弄 Resident IP 來弄。
  • YouTube Data API -> 需要 OAuth 流程,弄完只能抓自己的影片字幕。

後來最後發現 Gemini 2.5 模型支援抓取 YouTube URL 來分析(撒花!自己的服務就是不會阻擋啊~~)

image-20250808235727949

加入 n8n 流程來讓傳送訂閱最喜歡的影片摘要

幾件事情可以分享一下:

YouTube RSS Node

首先 https://www.youtube.com/feeds/videos.xml?channel_id= 這樣的網址就是一個頻道的 RSS 。這個可以當作 RSS Trigger Node

如何取得 YouTube Channel ID

image-20250809000847407

使用 YouTube Node - Get A Video ,放入影片或是 video ID 就可以看到 Channel ID 。

[好書分享] 別把你的錢留到死

別把你的錢留到死
懂得花錢,是最好的投資——理想人生的9大財務思維
Die with Zero : Getting All You Can from Your Money and Your Life
作者: 比爾.柏金斯  
原文作者: Bill Perkins  
譯者: 吳琪仁  出版社:遠流出版 

買書推薦網址:

前言:

這是 2025 年第 5 本讀完的書。 今年讀書的節奏大多是一本看一下,馬上跳過去看另外一本。 最近陸陸續續開始把一些書籍讀完,接下來讀完書籍的速度也會更快了吧。

大綱

第1章:最佳化你的人生
核心觀念:人生財富的分配應以最大化「生命活力」為目標。每個人積攢財富的方式不同,但核心問題在於如何在有生之年最佳化資源分配,以活出最充實的人生。

重點:書中強調「死前讓財產歸零」是一個值得追求的目標,這種思維能改變人們對金錢的慣性,從單純累積財富轉向追求有意義的體驗,進而實現最佳人生。

第2章:投資自己的人生體驗
核心觀念:提早投資於人生體驗能帶來「記憶股息」(memory dividend),即長期的情感與心理回報。

重點:
越早開始投資人生體驗(如旅行、學習等),越能享受記憶股息的「長尾效益」,因為年輕時的投資能產生更長久的回憶與滿足感。
隨著年齡增長,記憶股息的累積時間縮短,因此應儘早行動,將資源轉化為有意義的體驗。

第3章:為什麼死的時候要什麼都不剩
核心觀念:死前財產歸零的理念旨在避免浪費生命活力,鼓勵在有能力享受時積極使用資源,而不是留到無法使用的時候。

重點:
案例分析(如伊莉莎白的故事)顯示,過度儲蓄可能導致未能在生前充分享受財富,留下遺憾。例如,伊莉莎白在85歲去世時仍留有13萬美元,這些錢未能在她有能力享受時使用。
若熱愛工作,應尋找在工作之餘花錢從事喜愛活動的方式,平衡工作與生活樂趣。
心理抗拒「財產歸零」可能源自恐懼或習慣,建議反思抗拒根源,以更開放的心態面對這一目標。
幽默但深刻的建議:若賺到1500萬美元仍繼續工作,可能需要被「提醒」重新評估人生優先級。

第6章:生活要平衡
核心觀念:金錢的時間價值與個人利率(personal interest rate)隨著年齡增長而上升,因此應在生命早期或中期使用財富,以獲得最大享受。

重點:
金錢的時間價值:50多歲時的10萬美元比80多歲時更有價值,因為年輕時有更多精力與機會享受。
50/30/20法則:建議將收入分配為50%必要花費(房租、生活用品等)、30%個人需求(旅遊、娛樂等)、20%儲蓄與償債,作為簡單有效的財務管理方法,特別適合難以控制花費的人。
時間有限的觀念:人們常忽略生命的有限性,誤以為有「無限」的時間。提醒自己生命有限,才能更珍惜當下,充分使用資源。

第7章:開始為你的人生設定時間表
核心觀念:人生由多個階段組成,每個階段的「你」都會「死亡」,無法回頭,因此應為每個階段設定明確的目標與時間表。

重點:
每個人生階段(如青少年、大學生、單身時期等)結束後,該階段的你即「死亡」,無法重來。這提醒人們應及時行動,抓住當下機會。
設定時間表有助於將資源(時間與金錢)分配到最適合的階段,避免後悔。


第9章:要大膽,但不要愚蠢
核心觀念:年輕時應勇於承擔風險,因為時間充裕,允許失敗與恢復。

重點:
年輕時的風險承受能力較高,因為有時間從錯誤中恢復。隨著年齡增長,風險容忍度降低,因此應在早期大膽嘗試,但避免魯莽。

心得

這一本書就像是書籍封面一樣,先透過分享給你為什麼不要把錢留到死,該如何將錢能夠「儘量」的花完。最後再來討論,花錢是為了要讓自己人生的每一刻都要能完美,得到最大的滿足感。不要只是因為金錢的因素,而不斷地壓抑自己的快樂。這是一本讓你開始面對死亡,並且認真面對自己的內心的一本書。 讓自己要真誠追求自己想要的生活方式,不要因為想要將錢「存到老」而壓抑了自己整個人生的花費。

[Vibe Coding][Gemini CLI] 個人對 Vibe Coding 的一些感想

image-20250731145350802

»»» 想像力很重要 «««<

就像《葬送的芙莉蓮》裡的「尤貝爾」,產品開發時的「想像力」其實非常關鍵。這有點像「庖丁解牛」,你要能預想怎麼拆解問題,並且有效率地完成。Vibe Coding 就是這樣一個「已完成」的工具。(這比喻有點老派 XD)

舉個例子(這幾天應該會寫成文章),如果你想用 Agent 大軍來協助開發產品:

  • 不能只有一句話的需求。
  • 必須詳細描述你希望達成的功能(類似 PRD)。
  • 最好補充相關的背景知識,比如 Github App 或 Github Webhook,這樣可以省下好幾百塊的討論費用。

image-20250731145521001

個人對 Vibe Coding 的一些感想:

  • 一套好的開發流程和部署方式,能讓 Vibe Coding 發揮更大效益。這也是資深工程師和懂系統架構的人最明顯的差異。
  • 不要全然相信 AI,還是要扮演品質把關者的角色(無論你是老闆還是甲方)。
  • 資深工程師通常對 Vibe Coding 很樂觀,因為他們懂得檢查甚至修正 AI 的開發方式。

現在我的習慣是,開會前先讓 Vibe Coding 進 YOLO 模式跑一輪,再來檢查它做了什麼。其實用來開發 side-project,真的滿享受的!

[Python][Gemini CLI] 使用 LangChain 中的 Vertex AI 來處理 LINE Bot 中的圖片內容

前情提要

關於 Vertex AI 上面使用 Gemini 來做圖形偵測的架構圖

絕對可以!您的想法完全正確,這是解決這個問題的標準且唯一的途徑。

既然不能用一個「超級管理員」帳號(服務帳號)來處理所有事情,我們就必須讓每一個使用者授權您的應用程式來存取他們自己的 Google Drive。這就是 OAuth 2.0 的用途。

這個改動會比之前複雜很多,因為它引入了使用者互動的認證流程。我會為您詳細拆解。

宏觀概念:使用者授權流程

  1. 使用者發起連線:使用者在 Telegram 中對您的機器人發送一個指令,例如 /connect_drive。
  2. 產生授權連結:您的機器人會產生一個獨一無二的 Google 授權連結,並將它傳回給使用者。
  3. 使用者授權:使用者點擊連結,會被帶到 Google 的登入和授權頁面。頁面會顯示「TG Helper 想要存取您的 Google Drive」,使用者點擊「允許」。
  4. 重新導向並取得授權碼:Google 會將使用者重新導向到您預先設定好的一個網址(Callback URL),並附上一組一次性的授權碼 (Authorization Code)。
  5. 交換權杖:您的後端服務(Cloud Run)收到這個授權碼後,會用它跟 Google 交換一組存取權杖 (Access Token) 和一個非常重要的更新權杖 (Refresh Token)。
  6. 儲存權杖:您的應用程式需要一個資料庫(例如 Firestore),將使用者的 Telegram ID 和他們的更新權杖安全地儲存起來。
  7. 上傳檔案:當這位使用者之後傳送檔案時,您的機器人會:
    • 從資料庫中讀取這位使用者的更新權杖。
    • 使用更新權杖取得一組新的、有時效性的存取權杖。
    • 使用這組代表該使用者的存取權杖,將檔案上傳到他自己的 Google Drive。

新的架構

這個流程需要一些新的元件:

  • 一個 Web 端點:您的 Cloud Run 應用程式除了接收 Telegram 的 Webhook,還需要一個新的 HTTP 路徑 (例如 /oauth/callback) 來接收 Google 的重新導向。
  • 一個資料庫:用來儲存使用者 ID 和他們的 Refresh Token。最簡單的選擇是 Firestore,因為它與 Cloud Run 整合得很好,而且有免費額度。

實作步驟

步驟 1:Google Cloud Console 設定

  1. 設定 OAuth 同意畫面
    • 前往 OAuth 同意畫面 (https://console.cloud.google.com/apis/credentials/consent)。
    • 使用者類型:選擇「外部」。
    • 填寫應用程式名稱(例如 TG Helper Bot)、使用者支援電子郵件等資訊。
    • 範圍:點擊「新增或移除範圍」,找到並加入 …/auth/drive.file。這個範圍代表「僅允許上傳由本應用程式建立的檔案」,是權限最小、最安全的選擇。
    • 儲存並繼續。在「測試使用者」步驟中,將您自己的 Gmail 加入,這樣在應用程式發布前您才能進行測試。
  2. 建立 OAuth 2.0 用戶端 ID
    • 前往 憑證頁面 (https://console.cloud.google.com/apis/credentials)。
    • 點擊「建立憑證」 > 「OAuth 用戶端 ID」。
    • 應用程式類型:選擇「網頁應用程式」。
    • 已授權的重新導向 URI:這是最關鍵的一步。點擊「新增 URI」,然後輸入您的 Cloud Run 服務網址,並在後面加上一個回呼路徑,例如: https://tg-helper-xxxx-an.a.run.app/oauth/callback
    • 點擊「建立」。
    • 建立後,您會得到一組用戶端 ID (Client ID) 和用戶端密鑰 (Client Secret)。請將這兩者複製下來,它們非常重要。

步驟 2:啟用 Firestore 並安全地儲存密鑰

  1. 啟用 Firestore API

1 gcloud services enable firestore.googleapis.com

  1. 建立 Firestore 資料庫
    • 前往 Firestore 主控台 (https://console.cloud.google.com/firestore)。
    • 選擇「原生模式」(Native mode)。
    • 選擇一個離您最近的位置。
    • 建立資料庫。
  2. 安全地儲存 Client Secret 我們應該再次使用 Secret Manager 來儲存您在步驟 1-2 取得的 Client Secret。

1 # 將您的 Client Secret 貼在引號中 2 echo -n “YOUR_COPIED_CLIENT_SECRET” | gcloud secrets create tg-bot-client-secret –data-file=-

步驟 3:修改 Go 程式碼 (概念)

這將是一個較大的重構。我先不提供完整程式碼,而是描述邏輯上的變更:

  1. 新增 /connect_drive 指令處理:
    • 當收到此指令,程式會使用 Google 的 Go Auth 函式庫產生一個授權 URL。
    • 這個 URL 會包含您的 Client ID、redirect_uri、scope,以及一個 state 參數。state 參數通常會包含該使用者的 Telegram ID,以便在回呼時能識別是誰。
    • 機器人將此 URL 回傳給使用者。
  2. 新增 /oauth/callback HTTP 處理器:
    • 這個函式會處理來自 Google 的重新導向。
    • 它會從 URL 參數中取得 code 和 state。
    • 驗證 state 以確保請求的合法性,並從中解析出 Telegram User ID。
    • 使用 code 和您的 Client Secret 向 Google 交換權杖。
    • 將 (Telegram User ID, Refresh Token) 這組對應關係存入 Firestore。
    • 向使用者顯示一個「授權成功!」的簡單網頁。
  3. 重構 handleFile 函式:
    • 當收到檔案時,它會先用檔案傳送者的 Telegram User ID 去 Firestore 查詢。
    • 如果找不到對應的 Refresh Token,就回覆訊息請使用者先執行 /connect_drive。
    • 如果找到了,就用 Refresh Token 取得一個新的 Access Token。
    • 用這個 Access Token 建立一個 Drive 服務,然後上傳檔案。

[好書分享] 教練 - 價值兆元的管理課

教練 - 價值兆元的管理課,賈伯斯、佩吉、皮查不公開教練的高績效團隊心法
Trillion Dollar Coach : The Leadership Playbook of Silicon Valley’s Bill Campbell
作者: 艾力克.施密特  強納森.羅森柏格  亞倫.伊格爾  原文作者: Eric Schmidt  Jonathan Rosenberg  Alan Eagle  
譯者: 許恬寧  出版社:天下雜誌出版 

買書推薦網址:

前言:

這是 2025 年第 4 本讀完的書,今年讀完的書,真的有點少。不過這一本書還蠻有趣的,雖然不是 Bill Campbell 本人寫的團隊心法,反而是他過世後,由幾位作者找了許多矽谷的領導人訪談之後的一些心得整理,反而更加的珍貴。 讓人閱讀起來有許多相關的人物與背景,也更容易帶入相關的情境之中。

大綱

從球場到商場,超凡的高績效人士的身後,都有個教練。
即使是身經百戰的戰將,也有連自己都不知道的潛力;
面對沒有標準答案的選項,也需要指引,重新聚焦最重要的事!

從蘋果的庫克、Alphabet的漢尼斯與皮查,到臉書的祖克柏與桑德伯格,當今許多頂尖創業家、CEO、高階主管心中有疑惑時,他們都去問比爾.坎貝爾。

谷歌執行長皮查說︰「他總會適時協助我看清什麼才是最重要的事。」
YouTube執行長沃西基說︰「他能助人發揮潛能,促成團隊同心協力。」
矽谷創投之父杜爾說︰「比爾.坎貝爾是我見過最有智慧的人。」
蘋果執行長庫克說︰「他對蘋果的貢獻難以估算,也無可取代。每個人都可以向我們這個產業最偉大的教練學習。」

優秀的主管,必須先是優秀的教練;
一個人的職位愈高,他的成功就愈取決於能否幫助他人成功!

比爾從大學足球教練出身,四十三歲才進入矽谷。從帶球隊到教企業團隊,比爾都備受敬愛,因為他深諳每個人都希望被尊重、有價值的人性。他的教練之道不曾出現在任何官方文件,他也很少出現在主流媒體上。親密學徒施密特等人歷時超過兩年,採訪近百位業內頂尖人士,總結這位傳奇商業教父的管理智慧和領導哲學,闡釋建立信任、打造團隊、促進成長的32個管理黃金法則。

.不論個人發展或公司命運,都取決於人際關係的品質
.尋求最好的點子,若以達成共識為目標,只會導致團體迷思與較差決策
.每個人想要被喜愛、不想被背叛,激發正面的人性價值就會帶來正面的商業成果
.經理人的權威,來自部屬、同儕與長官的信任,而非權威式管理
.只指導願意受教的人,不必有教無類,不然你會很累

「教練就是跟你說你不想聽的話,要你看你不想看的事,最後讓你成就你想成就的關鍵人物」。每個人都可以從這本書學習如何教練自己和周圍的人變得更好。

這個世界面臨眾多挑戰,唯有靠團隊才能解決,而團隊都需要教練。在亟需領導力的時代,當今最有權力的CEO、創投家、創業者、高階主管們的共同教練,提供你突圍、成功的祕訣。

image-20250728143722873

image-20250728161440971

摘要聚焦於比爾·坎貝爾(Bill Campbell)的教練之道,涵蓋其領導哲學、社交能力、同理心、團隊管理及董事會運作等核心理念,強調信任、心理安全感及有效溝通的重要性。

1. 社交能力與人際連結

比爾強調建立人際關係是領導的基礎,鼓勵管理者主動與同事互動,關心他們的生活,並以真誠的問候建立連結。

  • 重要句子
    • 「試著培養這種人際關係對我來說並不容易,但我努力做到了。幸運的是,愈做就會愈覺得簡單。」
    • 「我曾試著記住大家的名字,在電梯裡碰到人的時候,我會試著開口和旁邊的同事聊聊,問候他們,問問他們最近如何?在忙什麼?」
    • 「善待身邊的人,是人生最有價值的投資。」
  • 比爾以簡單問候(如「家裡的人都好吗?」)拉近距離,先建立關係再處理工作,展現人性化領導風格。

2. 同理心與心理安全感

比爾的領導風格強調同理心,他以傾聽和觀察為基礎,提供適切建議,並創造讓團隊成員敢於表達的心理安全感。

  • 重要句子
    • 「比爾會傾聽與觀察。這是教練的能力,他能夠提供不一樣的觀點,帶你站在制高點看問題。」
    • 「在團隊中培養心理安全感,建立信任是關鍵。康乃爾大學曾在1999年研究中首次對心理安全感下了定義:『團隊成員一致認為可以在團隊中直言不諱,不必害怕會冒犯誰,那是一種團隊氣氛,讓人可以安心做自己。』」
    • 「信任是企業成功的基礎,但今日許多商業書已不再談論它……大家從比爾身上感受到最深刻的就是信任。」
  • 他鼓勵管理者以真誠回饋,承認問題並激勵團隊前進,確保成員感到被尊重和信任。

3. 解決問題與直面挑戰

比爾擅長找出並解決「房間裡的大象」,即那些被忽視的棘手問題,強調領導者應直面挑戰並優先處理。

  • 重要句子
    • 「找出大家避而不談的棘手問題,把它擺到所有人面前,然後優先解決,以免這些問題因辦公室政治繼續在公司裡悶燒,造成更大傷害。」
    • 「比爾會明確提出問題,強迫所有人都關注它,『不留任何空間給人搞辦公室政治』。」
    • 「只要有比爾在,房間裡永遠不會有大象。」
  • 他強調領導者應果斷承諾,專注於對團隊最好的選擇,並避免個人利益凌駕於團隊之上。

4. 有效溝通與積極聆聽

比爾推崇積極聆聽,強調專注傾聽、提問以釐清問題,並激發對方的效能感與歸屬感。

  • 重要句子
    • 「與人溝通時,首先要專注,把所有注意力放在聆聽對方說話;不要一邊聽,一邊想著自己接下來要講什麼。」
    • 「他從比爾那裡學到最重要的一件事,就是『把注意力放在面前的人,仔細聆聽,接著才開始討論,要達到真正有效的溝通,專注、聆聽、對話,是有先後順序的。』」
  • 他以說故事的方式引導他人自行做出最佳決定,而非強行命令。

5. 團隊管理與人才培養

比爾認為優質團隊是成功的關鍵,管理者應提供資源、尊重與信任,幫助人才成長並釋放潛能。

  • 重要句子
    • 「人才是任何公司的成功基礎。管理者的主要工作,就是協助部屬以更有效的方式完成工作,並從過程中有所成長。」
    • 「比爾是團隊教練,他的職責是建立團隊、型塑團隊,把合適的人放在合適的位置(以及讓不合適的人離開不合適他的位置)。」
    • 「做任何事都需要團隊的齊心協力。」
  • 他強調管理者應視部屬如孩子,引導他們走上正確道路,並以慷慨和尊重的態度處理離職事宜。

6. 董事會與高績效人才管理

比爾建議董事會應由具備營運實務經驗的人組成,並強調管理高績效但難相處的人才需平衡其貢獻與團隊和諧。

  • 重要句子
    • 「比爾告訴科斯托洛,你要有其他能仰仗的經營者。比爾也明確指出什麼樣的人是不好的董事:『那種人大搖大擺走進來,想當全場最聰明的人,而且話很多。』」
    • 「如何管理公司裡那些高績效、但難以相處的團隊成員,是管理者最頭痛的問題之一。」
    • 「如果這些恃才傲物的人,不斷把自己的利益看得比團隊更重要,就算再有才華,也不可容忍。」

7. 展現真誠與完整的人格

比爾以真誠和人性化領導聞名,強調管理者應展現完整的自己,並以信任和鼓勵激發他人潛能。

  • 重要句子
    • 「比爾從來不會在工作中刻意去除他的人情味。他也把每個人都當成一個完整的人來看待,有專業的一面、私下的一面、家庭的一面、情緒的一面,是全部面向加起來的一個完整的人。」
    • 「教練就是跟你說你不想聽的話,要你看你不想看的問題,最後讓你成就你想成就的人。」
    • 「比爾總是能把勇氣傳遞給我,而我也總是會因此受到鼓舞。我從比爾身上學到一點:要做一個給予別人能量的人,而不是一直消耗別人能量的人。」

8. 領導者的角色與責任

比爾認為領導者的核心在於做事並帶來影響力,而非僅靠頭銜或個人成就。他強調管理者應以公司利益為先,並以身作則。

  • 重要句子
    • 「你以前做什麼不重要,你現在想什麼也不重要,重點是你每天做了什麼。」
    • 「頭銜使你成為管理者,部屬使你成為領導人。」
    • 「管理者的第一要務,就是確保自己帶領的人既幸福又成功。」

心得

當初會看到這本書,只是沒有想到一個足球教練出身的比爾,竟然能成為百大 CEO 們的團隊導師。

這一本書給我很大的啟發,主要是領導團隊的方面。裡面有許多部分給我很多新的想法:

  • 帶領團隊,從「人」開始:
    • 很多時候,會覺得是制度對了。團隊應該會往正確的方向走下去,但是看起來,團隊中的人還是最大的因素。
  • 找出團隊問題中的「屋裡的大象」:
    • 「屋裡的大象」就是團隊中很明顯的問題,但是往往大家會忽略他。或是以為不需要去處理它,

這些案例,還有我上面相關書籤的文字其實都給我蠻多的想法的。也讓我知道,團隊中的重要問題,可能需要在許多會議前去解決掉。也很推薦許多想要領導團隊的人一起來看這一本書。

[Python][Gemini CLI] 使用 LangChain 中的 Vertex AI 來處理 LINE Bot 中的圖片內容

image-20250305221818691

前情提要

之前 [Python] 在 LangChain 中將 Gemini 換成使用 Vertex AI 曾經有分享給大家該如何使用 LangChain 中的 Vertex AI 的相關功能。它具有以下的優點:

  • 如果你專案放在 GCP CloudRun ,不需要額外放 Gemini API Key。可以更安全處理自己程式碼的安全性。
  • 使用了 VertexAI 還有許多相關進階功能可以使用,之後也可以慢慢分享。

這一篇文章主要寫程式的部分都是使用 Gemini CLI :p ,但是有一些地方也跟大家講一下如何跟 AI 來溝通才能避免錯誤卡住。

範例程式碼:

https://github.com/kkdai/linebot-gemini-python (大家可以參考 )

(透過這個程式碼,可以快速部署到 GCP Cloud Run)

關於 Vertex AI 上面使用 Gemini 來做圖形偵測的架構圖

image-20250728100915757

這一張網路的圖解釋得很清楚,這邊要記得由於 VertexAI 使用到 Gemini 圖片相關處理的時候,必須要使用到 GCS (Google Cloud Storage) ,所以你不能只是放某個網路圖片網址給他,而是必須要將圖片放入 Google Cloud Storage 的 Bucket 之中,才能處理。

這裡程式碼會有一些相關的修改,就會有以下的相關部分來解釋:

如何將圖片上傳到 GCS

  • 記得先到 GCS 建立一個新的 Bucket ,並且把這個名稱保持下來。放在環境變數上。 (這裡使用 GOOGLE_STORAGE_BUCKET )
  • 由於我們偵測完圖片後,就不會再次使用到他,所以可以馬上從 GCS 刪除,避免不小心沒刪除到,然後記得到 Lifecycle 設定一天的生命週期。

image-20250728101738917

要小心 Gemini CLI 使用 LINE Bot 套件造成不段重複錯誤

這邊要小心,即便我的 Gemini CLI 已經有使用了 Contex7 這個 MCP Server ,使得 Gemini CLI 永遠會去讀取最新的套件資訊。但是有時候,還是會卡住,這邊舉一個例子:

Google Chrome 2025-07-28 10.23.28

這是一個 我請 Gemini CLI 直接去開發如何使用 LangChain 中的 Vertex AI 來直接將 LINE Bot 圖片直接放到 GCS (Refer commit)

這邊會發現,其中會發現,他從 line_bot_api.get_message_content(event.message.id) 取得的物件,一直無法成功的取得相關的 stream 資訊。這邊我大改跑了三~四次的 prompt 都無法成功,所以只好人工下來請他修改一下:

其實我本來有先複製正確的寫法,請他幫我順一下之後:

  message_content = await line_bot_api.get_message_content(event.message.id)

  # Asynchronously read all content chunks into a byte string
  image_bytes = b''
  async for chunk in message_content.iter_content():
      image_bytes += chunk

  # Create an in-memory binary stream from the bytes
  image_stream = BytesIO(image_bytes)
  # Reset the stream's pointer to the beginning for the upload function
  image_stream.seek(0)

他還是會把它改回去,我只好又一次的糾正他,這時候才會正確。

image-20250728103206712

這時候才會寫正確 (Refer commit) :

Google Chrome 2025-07-28 10.23.32

相關程式碼,放一下:

        elif (event.message.type == "image"):
            user_id = event.source.user_id
            print(f"Received image from user: {user_id}")

            message_content = await line_bot_api.get_message_content(
                event.message.id
            )

            # Asynchronously read all content chunks into a byte string
            image_bytes = b''
            async for chunk in message_content.iter_content():
                image_bytes += chunk

            # Create an in-memory binary stream from the bytes
            image_stream = BytesIO(image_bytes)
            # Reset the stream's pointer to the beginning for the upload
            image_stream.seek(0)

            file_name = f"{uuid.uuid4()}.jpg"
            gcs_uri = None
            # Default error message
            response = "抱歉,處理您的圖片時發生錯誤。"

            try:
                gcs_uri = upload_to_gcs(
                    image_stream, file_name, google_storage_bucket)
                if gcs_uri:
                    print(f"Image uploaded to {gcs_uri}")
                    response = generate_image_description(gcs_uri)
            finally:
                # Clean up the GCS file if it was uploaded
                if gcs_uri:
                    delete_from_gcs(google_storage_bucket, file_name)

            reply_msg = TextSendMessage(text=response)
            await line_bot_api.reply_message(
                event.reply_token,
                reply_msg
            )
        else:
            continue

由於 GCS 相關使用方式,都是直接使用,大家快速參考即可:

def upload_to_gcs(file_stream, file_name, bucket_name):
    """Uploads a file to the bucket."""
    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(file_name)

        blob.upload_from_file(file_stream, content_type='image/jpeg')

        # Return the GCS URI
        return f"gs://{bucket_name}/{file_name}"
    except Exception as e:
        print(f"Error uploading to GCS: {e}")
        return None

成果:

image-20250728105409436