產品功能影片技能
為真實、正在運行的產品規劃並建構一個展示/功能影片——透過 Playwright 在真實螢幕上擷取畫面、使用真實的 TTS 進行旁白、搭配真實(開源、授權乾淨)的音樂背景,並在 Remotion 中組裝。這與合成的動態圖形產品預告片是截然不同的領域:素材已經存在且無法重新繪製以符合腳本,因此腳本必須配合素材。
與合成動態圖形預告片的關鍵差異
許多 Remotion 影片工作流程假設您可以控制每個像素並隨時重新調整時間——因為整個影片是從頭開始建構的:模型、生成的背景、發明的 UI。這個假設在這裡不成立。真實的螢幕錄影有自己的時間軸;真實的點擊發生在某個特定影格,而不是分鏡表想要它發生的時候;有些時刻(原生 OS 視窗、瀏覽器自己的工具列、在半秒內完成的互動)根本無法重新拍攝以符合腳本。此技能從根本上就是圍繞這個限制而建構的——動態設計工藝(緩動、轉場、動態密度)仍然重要,並在第 8 階段涵蓋,但流程的真正骨幹是素材驅動影片特別需要的東西:針對無法捕捉時刻的原型備援審計、針對真實素材上縮放和點擊強調的穩定性驗證定位,以及由實際素材時長而非腳本驅動的時間安排。
核心原則:真實素材優先,原型其次,插圖最後
對於每個場景,按此順序優先考慮:
- 真實素材——實際運行應用程式的實際 Playwright 錄製。
- 經審查的 HTML 原型——以相同方式捕捉,用於真實素材在結構上無法顯示的任何內容(參見第 2 階段)。
- 一個誠實、清楚說明的佔位符——僅在上述兩者都無法實現時使用,且僅在它不冒充真實素材的前提下。
絕不要用偽裝成真實素材的選項 3 來偽造選項 1。觀眾信任展示影片正是因為它是真實的;一個看起來是偽造的瞬間會破壞所有真實瞬間的可信度。
第 0 階段:簡報
在進行任何其他事項之前,先一起詢問一次:
- 產品與儲存庫——名稱、一句話描述、運行中應用程式或儲存庫的 URL/本地路徑。
- 受眾與調性——誰在看,他們應該感受到什麼(印象深刻/安心/興奮)?
- 時長——30 秒預告、60-90 秒導覽、或更完整的 2-3 分鐘導覽?真實素材很快就會變長;要誠實評估範圍。
- 必須留下印象的那個時刻——如果觀眾只記得一件事,那是什麼?這將成為高潮/英雄時刻。
- 登入/測試帳號——捕捉應用程式需要帳號嗎?能否建立一個一次性的展示帳號,或者已經存在?
- 發布情境——登陸頁面、YouTube、社交動態(自動靜音播放對字幕/螢幕文字決策影響很大)。
如果產品是瀏覽器擴充功能,也請詢問是否涉及 Manifest V3(會改變 Playwright 啟動策略——參見第 6 階段)。
第 1 階段:偵察——提取真實的設計系統,不要發明一個
在任何美學決策之前,先閱讀實際產品:
- 從應用程式自己的 CSS/主題檔案中提取真實的色彩 Token、字型堆疊和間距比例。按原樣使用它們,即使強調色碰巧像一個「通用的 AI SaaS」陳腔濫調(在真實產品調色盤中,靛藍/紫色搭配近黑色也極為常見——只有當它是發明的預設值而不是實際產品時,才是危險信號)。在此,真實性勝過新奇。
- 注意產品實際的 UI 文案、術語和資訊架構——影片的字幕和旁白應使用應用程式自己的詞語,而非行銷改寫。
- 像使用者一樣,完整運行應用程式一次。確定:什麼是單一最佳的「英雄」互動?什麼是真正難以即時展示的(參見第 2 階段)?
將提取的 Token(顏色、字型)儲存到一個 tokens.ts/tokens.css 檔案中,整個影片專案從一個地方匯入——每個場景,無論是真實的還是程式建構的,都應明顯屬於同一個產品。
第 2 階段:原型備援審計(在分鏡表之前執行)
瀏覽計劃的功能列表,並標記 Playwright 在結構上無法捕捉的任何項目:
- 作業系統層級的瀏覽器 chrome——擴充功能工具列圖示、
chrome://extensions、右鍵選單、原生檔案選取器、原生作業系統對話框。Playwright 的recordVideo只捕捉頁面內容,絕不捕捉瀏覽器自己的 UI。 - 原生桌面殼層(Tauri、打包後的 Electron、Qt 等)——這些根本不是 Playwright 可以附加的網頁。
- 太快或太小而無法可靠展示的互動——在真實素材中,一個在不到半秒內完成的切換開關,是裁剪放大或點擊強調環的糟糕目標;兩者都需要一個穩定的多影格視窗來定位(參見第 8 階段的 ZoomCue/ClickRing 模式及其穩定性規則)。
對於每個被標記的時刻,決定:帶有變通方法的真實素材(例如,透過 API 呼叫設定狀態而不是實際點擊,如第 6 階段所述)、一個經審查的 HTML 原型(第 7 階段)、或一個誠實標註的插圖(最後手段,並在程式碼註解中說明)。
在分鏡表之前而非之後執行此審計,可以防止分鏡表承諾實際捕捉步驟無法達成的時間安排和覆蓋範圍——這是 TabNemo 從 v1 到 v3 中最大的返工來源。
第 3 階段:分鏡表與場景規劃
敘事弧線
無論素材是真實的還是合成的,同樣的結構都適用:
| 幕 | 目的 | 佔比時間 |
|---|---|---|
| 鉤子 | 冷開場——問題,或一個引人注目的時刻,在產品名稱出現之前 | 5-8% |
| 揭露 | 品牌/產品名稱出現 | 8-10% |
| 展示 | 3-5 個真實功能,每個一個重點 | 45-55% |
| 高潮 | 第 0 階段確定的英雄時刻——給予最多的視覺關注 | 8-12% |
| 結尾 | Logo、標語、CTA | 8-10% |
每個場景的規格
對於每個場景,預先決定並寫下:
- 來源:真實片段 / 原型捕捉 / 程式建構的 B-roll(根據第 2 階段的審計)。
- 旁白:確切文字,或
null。旁白長度是真實的限制——TTS 音訊時長將成為場景的最短長度(參見第 4 階段)。 - 真實素材有自己的時間軸——場景的
durationInFrames是max(實際片段長度, 旁白長度),從實際渲染的素材中探測得出,永遠不要從計畫中假設。如果旁白比片段長,則保持片段的最後一幀,而不是循環播放或切斷台詞。 - 鏡頭規劃:任何放大/縮小或點擊強調,帶有實際座標——從實際靜止畫面決定,而非猜測(第 8 階段)。
審查檢查點
在錄製任何一個片段或生成任何一音訊之前,先展示場景列表 + 旁白文字。一個基於對可用素材錯誤假設的計畫,一旦 TTS 和 Playwright 腳本存在,就很難撤銷。
第 4 階段:旁白——腳本與生成
撰寫兩個文件,而非一個:
- 審查腳本——每個場景一個區塊,附上其規劃的時間碼,讓人類可以閱讀整個旁白弧線並在生成前批准節奏。
- TTS 輸入腳本——相同的台詞,按場景分割成單獨的檔案,節奏僅由標點符號(或 SSML 的
<break>/<emphasis>標籤,如果引擎支援)承載,以便每個場景成為可以放置在自己偏移位置上的獨立音訊片段。
生成工具
- ttsmp3.com ——免費,無需註冊,由 Amazon Polly 支援。沒有公開 API,因此生成是透過瀏覽器 UI 一次一個片段——預留一個專注的時段來完成所有片段,並按場景命名輸出檔案(
scene-03.mp3,而不是tts_export_1.mp3)。 - 對於需要無人值守運行的流程(CI、沒有瀏覽器參與的代理),請改用實際可腳本化的開源/本地選項:Piper(完全離線,MIT 許可,快速,聲音不錯)或 edge-tts(包裝 Microsoft Edge 的朗讀聲音,免費,無需金鑰,可腳本化,但依賴於保持可用的外部服務)。如果 API 成本可以接受,Gemini TTS 和 ElevenLabs 是強大的非開源替代方案。無論哪個引擎,如果它不保證跨不同呼叫的聲音一致性,請在單一請求中生成所有片段,並在它們之間使用暫停標記,然後根據檢測到的靜音進行分割——這一個技巧無論引擎如何,都能解決「每行台詞聲音不同」的問題。
生成後——音訊是事實的來源
探測每個生成檔案的真實時長(不要相信估算)。將真實時長傳播回場景規劃的時間安排中。這一個步驟解決了 TabNemo 建構中所有的時間錯誤——旁白是觀眾用來衡量一個場景的耳朵標準,因此,是它(而不是計畫)設定了時鐘。
第 5 階段:背景配樂——獲得一個朗朗上口的音樂,且沒有授權地雷
一個平淡的 pad 和 drone 循環聽起來像電梯背景音樂,而不是一個「朗朗上口的」音樂背景——其差異幾乎總是一個重複的旋律鉤子,而不僅僅是和聲 pad。三個真實選項,按「最安全的授權」到「最可靠地朗朗上口」排序:
選項 A——程序化合成(零授權風險,需要真正努力才能聽起來不平淡)
在純 Node/Python 中生成一個簡短、可無縫循環的立體聲 WAV——沒有模型、沒有依賴項、完全沒有授權問題,因為你編寫了每個樣本。有效的具體配方:
- 一個使用簡單振盪器(正弦/三角波)搭配慢起音/釋放包絡的短(8-16 小節)和弦循環——單獨這一點就是「電梯音樂」陷阱;它不是鉤子。
- 實際的鉤子:一個在其上方的 Karplus-Strong 撥弦旋律,使用固定的重複節奏模式,比 pad 高一個八度——這就是讓合成循環令人難忘而不是環境背景的關鍵。不要跳過這一層。
- 一個柔和的底鼓 + 節拍脈衝在下方提供前進感,音量要夠小以便放在旁白之下。
- 標準化以保留餘量,選擇循環長度使整個進行在小節邊界上完成(沒有可聽到的接縫)。
這在商業上完全安全,但旋律鉤子層是區分「朗朗上口」和「普通」的關鍵——預留真正的迭代時間,並在將其接入完整渲染之前讓使用者收聽確認(重新生成一個 15-20 秒的循環很便宜;重新渲染整個影片來試聽一個不同的循環則不然)。
選項 B——開放權重的生成音樂模型(感覺更「製作出來」,每次都要檢查授權)
- Stability AI 的 Stable Audio Open ——開放權重,文字提示,確實能產生帶有真實旋律內容的完整編曲。授權條款比大多數生成音訊模型更寬鬆,但確實帶有基於收入的條件——在任何商業使用前請重新閱讀當前授權,因為這些條款會變動。
- Meta 的 MusicGen(透過
audiocraft函式庫)——品質極佳,但其音樂模型權重通常以 CC-BY-NC(非商業)授權——不要在貨幣化產品的上市影片中使用生成的輸出,除非單獨獲得授權。 - 兩者都可以在本地運行(建議使用 GPU)或透過託管推理端點(Replicate、Hugging Face Spaces)運行,如果本地算力不可用。
選項 C(推薦預設)——使用 B 獲取靈感,使用 A 獲取資產
在本地提示一個開放權重模型僅供靈感(「朗朗上口的合成流行鉤子,~110bpm,溫暖樂觀的科技產品感覺」),聽一些生成結果來完善你的想法,然後使用選項 A(程序化合成) 建構實際運送的資產。這樣你就能獲得旋律的最佳點,而不會讓你的影片依賴於一個未來可能改變授權條款的模型。
第 6 階段:Playwright 捕捉器——為素材設計,而非為陳述設計
基礎設定
- 使用
playwright.config.ts中的video: 'on'(完整錄製)或video: 'retain-on-failure'(CI 除錯),但對於素材捕捉,偏好'on'。 - 設定
viewport: { width: 1920, height: 1080 }以獲得乾淨的 1080p 素材。 - 在每個場景錄製前,凍結瀏覽器(
await page.pause()或await page.waitForTimeout(3000))——這會給予一個穩定的、無動畫的初始影格,用於 Remotion 中的平滑剪輯切入。
設定狀態——偏好 API 而非 UI
不要在你的展示流程中點擊登入表單:
當適用時,呼叫 POST /api/setup-demo-state 或設定 localStorage/sessionStorage、cookie。這不僅更快,還能避免在成品影片中顯示登入畫面、載入旋轉器和網路延遲。在腳本頂部有一個 seedState(page, state) 輔助函式。
瀏覽器擴充功能的啟動
對於Manifest V3擴充功能,標準的 chromium.launch({args: ['--disable-extensions-except=...']}) 會被瀏覽器的擴充功能服務工作者啟動延遲所絆倒。有效的解決方案:
const browser = await chromium.launchPersistentContext(tempUserDataDir, {
headless: false, // MV3 服務工作者需要一個真實的瀏覽器視窗
args: [
`--disable-extensions-except=${path.resolve(extensionPath)}`,
`--load-extension=${path.resolve(extensionPath)}`,
'--no-sandbox', // 在 CI/Docker 中需要
],
});
然後對擴充功能的彈出頁面本身:const popupPage = await context.newPage(); await popupPage.goto('chrome-extension://<你的擴充功能 ID>/popup.html');。這繞過了點擊工具列圖示的需要,而工具列圖示是 Playwright 無法做到的。
錄製後——將語音轉文字當作初始編輯層
將每個錄製的 WebM 通過 whisper.cpp 或你的偏好的語音轉文字模型。與其在 Remotion 中手動剪輯靜音,不如使用語音轉文字的逐字時間碼作為編輯決策列表(EDL)的基礎:識別暫停、快速說話和其他編輯提示。這特別有價值,因為旁白腳本不是自由形式——它是固定的——所以你可以將旁白時間碼對齊到語音轉文字的輸出以獲得精確的場景邊界,而不需要猜測。
第 7 階段:原型場景(B-roll 與無法捕捉的元素)
何時以及為何建構原型
原型用於 Playwright 在結構上無法捕捉的螢幕元素——而不是用於那些你更喜歡它是合成而非真實的場景。第 2 階段的審計決定了這一點;始終先嘗試真實的 Playwright 捕捉。當真實捕捉不可能時,原型應為此效勞:
- 展示一個原生對話框的近似外觀(例如,一個作業系統風格的確認對話框,用於你無法在 Playwright 中觸發的權限提示)
- 繪製一個瀏覽器工具列圖示在上下文中的位置(對於某些無法截圖的擴充功能)
- 演示一個桌面應用程式的登入畫面,該應用程式的其餘部分是網頁
建構規範
- 對齊到產品的設計 Token(與
tokens.ts/tokens.css相同)——原型不應該顯得「像另一個產品」。 - 使用與真實素材相同的 viewport 大小(1920x1080)進行捕捉。
- 在原型原始碼中加入一個「此為模擬」的疊加層(一個微妙的點狀邊框或角落浮水印,在最終渲染中是可選的,但可以防止你的審查步驟混淆真實素材和原型)。
- 保持靜止——原型不應該有它自己的獨立動畫,因為它將從 Playwright 錄製的上下文中播放,該錄製已經有自己的時間軸。
工具選擇
- 簡單的 HTML/CSS/JS 嵌入在一個 Playwright 腳本中(
page.setContent())——這是最快、最真實的,因為它使用了 Playwright 自己的渲染管道。 - Tailwind / 你的產品現有元件庫——如果你可以從產品構建中匯入元件,建立一個靜態 HTML 頁面,你可以在 Playwright 中捕捉。
- 不要把 Figma 原型或靜態圖像放入 Playwright——它們在影片中看起來會模糊且脫離上下文。
捕捉
與真實素材相同:使用 Playwright 的 page.screenshot() 和 page.video(),在同一個腳本流程中,以獲得一致的色彩空間和壓縮設定。
第 8 階段:運動設計——將真實素材與動態效果結合
規則 1:素材決定編輯,而不是反過來
你正在編輯一個既有序列的節奏,而不是設計一個新的序列。你的剪輯點是:
- 語音轉文字確定的旁白中的停頓
- 錄製中捕捉的自然互動邊界
- 由提示驅動的 LLM 決定的順暢鏡頭組合
提示驅動的鏡頭挑選
不要自己決定從一分鐘的 Playwright 錄製中剪輯哪些 5 秒片段。作為替代:
- 將語音轉文字的輸出提供給一個 LLM,提示它從錄製的內容中為旁白的每一行選擇最佳的時間碼。每行範例:
"在用戶點擊「開始」按鈕的錄製中,找到時間碼 00:00:12.000 到 00:00:14.500。輸出 JSON:
{\"scene\": \"scene-03\", \"targetLine\": \"...\", \"clipStart\": 12.0, \"clipEnd\": 14.5}" - 然後使用該 JSON 在 Remotion 的
offthreadvideo或<Video>元件中設定startFrom和durationInFrames。
這適用於複雜、反應性的 UI 演示,在這些演示中,互動序列並非線性,你需要從它們的上下文中「摘取」最佳時刻。
ZoomCue(放大)和 ClickRing(點擊環)模式
在真實素材上,你不能依賴合成動畫的把戲(將 UI 元素移入畫面或淡化它們)。你的工具僅限於:
ZoomCue: 一個平穩、緩動的縮放,進入影片片段中的一個特定 UI 區域。_
- 從錄製中挑選一個靜止影格(使用上面的語音轉文字 + LLM 方法)來決定確切的 X、Y、寬度和高度。
- 在 Remotion 中:對整個影片片段應用一個緩動的
style={{ transform: scale(...), transformOrigin: '...' }}。 - 縮放必須是平滑的(使用
ease-in-out緩動函式,持續 500 毫秒以上)並且短暫的(最多持續 2-3 秒,否則會迷失方向)。 - 只有在目標 UI 區域在整個縮放持續時間內保持靜止或接近靜止時才縮放。對於動畫加載旋轉器或即時更新饋送不要使用 ZoomCue。
ClickRing: 一個環形狀元素,與真實光標重疊,以引導注意力到一次點擊。_
- 找到點擊發生的確切影格(透過錄製中的遊標位置)。
- 放置一個 CSS
border-radius: 50%環(你可以從圓心動畫縮放),在點擊影格前 5-10 影格開始。 - 計算精確的 X/Y 位置可能需要以下組合:
// 從 Playwright 錄製的 JSON 日誌或網頁截圖 const clickPosition = { x: 960, y: 540 }; // 在 1920x1080 素材中 const ringStartFrame = clipStartFrame + clickFrameOffset - 5;
穩定性規則(這比所有的運動更重要)
如果該縮放或環形的目標在該影片片段中移動或發生巨大變化,不要使用 ZoomCue 或 ClickRing。 穩定 UI 在真實素材中很少見;避免在加載螢幕、表格即時更新或輪播滑塊上放置點擊強調。使用影片片段的靜止影格進行穩定性檢查,然後再提交到運動設計。
動態密度
- 目標是低動態密度素材:每 3-5 秒一次剪輯或相機移動。
- 在一個場景中不要使用兩個以上的 ZoomCue 或 ClickRing。
- 將你的縮放安排到旁白的節奏:當旁白在描述一個 UI 元素時使用 ZoomCue,當它在暫停或轉換到一個新想法時切換鏡頭。
第 9 階段:組裝與渲染
Remotion 設定
- 使用
@remotion/cli進行渲染。npx remotion render或你的自訂渲染腳本。 - 使用
useCurrentFrame()和useVideoConfig()在你的場景元件中。 - 保持每個場景元件小而專注:不要有超過 20-30 行邏輯的巨型場景。
渲染設定
- 編解碼器:
h264(適用於 YouTube/網路觀看)或vp8(適用於社交自動播放,如果檔案大小是一個問題) - 音訊:44100 Hz 採樣率,128 kbps 或更高的比特率
- 解析度:1920x1080(除非另有說明)
- 影格率:30 fps 適用於 web/RU 捕捉(與 Playwright 的預設捕捉相符),24 fps 適用於更「電影感」的感覺
輸出格式
out/video.mp4——主要的最終輸出。out/video-with-captions.mp4——內嵌播放在社交平台上靜音觀看的字幕。- 可選:
out/thumbnail.png——一個靜止影格,用於 YouTube 縮圖的關鍵影格。
字幕(內嵌式 v.s. 燒錄式)
對於社交自動播放(Instagram、X、Facebook): 將字幕燒錄到影片中。它們必須在沒有音訊的情況下也能閱讀。使用大、高對比度的無襯線字體(例如 Inter 或 SF Pro,使用粗體)。
對於 YouTube: 提供 .srt 或 .vtt 作為單獨的附件——對於使用者的可訪問性和翻譯工具更好。
第 10 階段:品質檢查與審查
自動化的
- 「顏藝檢測」 ——使用 FFmpeg 的
scene detect過濾器來確保 Playwright 捕捉中沒有意外的螢幕閃爍或瀏覽器凍結。ffmpeg -i input.webm -filter:v "select='gt(scene,0.4)',showinfo" -f null - - 音訊電平標準化 ——確保 TTS 和音樂背景不會削波。
ffmpeg -i audio.mp3 -af loudnorm=I=-16:LRA=11:TP=-1.5 output_normalized.mp3 - 持續時間檢查 ——驗證每個場景的持續時間與旁白和素材的持續時間匹配。
手動的
- 完整觀看至少一次,使用旁白。尋找剪輯跳動、音訊/影片同步問題、以及在章節之間感覺不對的「尷尬」轉場。
- 在社交平台上測試——如果發佈到 X 或 Instagram,在該平台上觀看完整影片。字幕可讀嗎?縮圖看起來好嗎?自動播放正確嗎?
- AB 比較——將你的影片與該產品現有的行銷資料(如果有的話)進行比較。它是否感覺屬於同一個產品家族?
附錄 A:支援的工具與庫
- Playwright:
npm create playwright用於初始設定。注意:Playwright 1.40+ 的video: 'on'選項會產生 webm 檔案。 - Remotion:
npx create-video。在 Remotion 4.0 中,你可以使用<OffthreadVideo>來載入大型影片而無需耗盡記憶體。 - FFmpeg:用於後期處理(標準化、字幕燒錄、場景檢測)。
- whisper.cpp:用於語音轉文字。
- Meta 的 MusicGen / Stability AI 的 Stable Audio Open:用於生成音樂靈感。
- TTS(語音合成):Piper(本地)、edge-tts(可腳本化、免費)、或 ttsmp3.com(基於 UI、免費)。
附錄 B:常見陷阱
| 陷阱 | 解決方案 |
|---|---|
| Playwright 捕捉到一個空白的瀏覽器視窗 | 確認你的擴充功能 ID 正確,且 load-extension 路徑是絕對路徑 |
| TTS 聲音在場景之間變化 | 在一個請求中生成所有台詞,使用暫停標記,然後按靜音分割 |
| 音樂背景淹沒了旁白 | 將音樂背景標準化到 -20 LUFS 或更低,並使用側鏈壓縮 |
| 一個 zoom 放大到錯誤的 UI 區域 | 在決定 X/Y 座標之前,使用靜止影格進行穩定性檢查 |
| 影片在社交平台上自動播放時顯得糟糕 | 從頂部 10% 開始,第一秒不要有淡入——這適用於自動播放 |
| 旁白與素材不同步 | 使用語音轉文字時間碼作為編輯決策列表(EDL)——見第 6 階段 |
附錄 C:TTL 與時效性
此技能的輸出僅在應用程式 UI 和功能不變的情況下有效。給定現代 SaaS 產品的部署速度,假設一個30 天的保鮮期。如果應用程式的儀表板、設定或核心互動流程發生變化,產生的素材和影片將需要重新擷取和重新渲染。將此工作流程與你的 CI 管道掛鉤,可以讓演示版本與產品保持同步。
從 TabNemo v1-v3 學到的經驗教訓
此工作流程是從建構和重建名為 TabNemo 的瀏覽器擴充功能的三個版本的所有權的展示影片中學到的經驗教訓的直接提煉。關鍵的法規:
- 素材第一,腳本第二。 先錄製,然後圍繞那些錄製的內容撰寫旁白腳本。
- 永遠不要跳過原型審計。 第 2 階段在創意不佳的日子裡節省了你,在創意好的日子裡則不然——無論如何都要執行它。
- 旁白驅動時鐘。 時長來自 TTS 音訊,而不是分鏡表頁。
- 保持旋律鉤子。 一個好的音樂背景是聽得到的,而不是聽不到的。
- 低動態密度素材適用於 UI。 完美的點擊環不會拯救一個混亂的鏡頭。
- 將這作為一個腳本運行,不要作為一個圖形應用程式。 此流程中的一切(從 Playwright 錄製到 Remotion 渲染)都可以從 CLI 運行。
- 提示你的 LLM 來選擇鏡頭。 透過詢問一個 LLM 從語音轉文字輸出中選擇片段,自動化從長 Playwright 錄製中挑選最佳時刻的過程。