zoom-lecture-publish

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

zoom-lecture-publish

zoom-lecture-publish

PORSEO LMS / AI PLAY GUILD の Zoom 録画を、講義データ・サムネ・Mux・Convex・Discord・note記事ハンドオフまで一気通貫で扱う。
Handles Zoom recordings from PORSEO LMS / AI PLAY GUILD end-to-end, including lecture data, thumbnails, Mux, Convex, Discord, and handoff to note articles.

守ること

Things to Follow

  • 本番作業では、対象サイトが使っている Convex URL を必ず確認する。ローカルの
    .vercel/project.json
    npx convex
    のデフォルト接続を信用しない。
  • Vercel/Convex/Zoom/Discord/Mux の secret は出力しない。ログにも貼らない。必要なら一時
    .env
    に読み込み、最後に削除する。
  • 公開は canary で1本だけ先に試す。
    getPublishedVideos
    muxPlaybackId
    thumbnailUrl
    が見えるまで確認してから一括公開する。
  • Discord投稿は自動投稿を待ち、active/public archived threads を確認して重複投稿を避ける。
  • LMS公開が完了したら、同じ素材を使って
    $note-membership-lecture
    に引き継ぎ、noteの編集可能な下書き・有料ライン・ライトプラン会員限定設定まで作る。単発購入価格はユーザーが明示した場合だけ付ける。noteの公開だけはユーザーの明示確認なしに実行しない。
  • ユーザーが「講義にはあげない」「noteだけ」「LMSには出さない」と言った場合は note-only 分岐 として扱い、Convex動画作成、Mux取り込み、公開、Discord通知を実行しない。
  • note-only 分岐でも note公開は明示確認なしに実行しない。まず編集可能な下書き、note用アイキャッチ、本文スクショ、プレビューまでで止める。note-only はデフォルト無料公開向けにし、有料ライン・会員限定・単発購入設定はユーザーが明示した場合だけ入れる。
  • 誤公開を消すときは Convex だけでなく、Mux asset と Discord forum thread も確認する。
  • In production operations, always confirm the Convex URL used by the target site. Do not trust the default connections in local
    .vercel/project.json
    or
    npx convex
    .
  • Do not output secrets for Vercel/Convex/Zoom/Discord/Mux. Do not paste them into logs either. If necessary, load them into a temporary
    .env
    file and delete it afterward.
  • Test with only one video in canary before full publishing. Confirm that
    muxPlaybackId
    and
    thumbnailUrl
    are visible via
    getPublishedVideos
    before bulk publishing.
  • Wait for automatic Discord posts, and check active/public archived threads to avoid duplicate posts.
  • After completing LMS publishing, use the same materials to hand off to
    $note-membership-lecture
    , creating an editable draft, paywall, and Light Plan member-only settings for note. Add a one-time purchase price only if explicitly specified by the user. Do not publish note articles without explicit confirmation from the user.
  • If the user requests "Don't upload as a lecture", "Only note", or "Don't publish to LMS", handle it as the note-only branch and skip Convex video creation, Mux import, publishing, and Discord notifications.
  • Even in the note-only branch, do not publish note articles without explicit confirmation. Stop at creating an editable draft, note eye-catching image, body screenshots, and preview. The note-only branch defaults to free publishing; add paywall, member-only, or one-time purchase settings only if explicitly specified by the user.
  • When deleting incorrectly published content, check not only Convex but also Mux assets and Discord forum threads.

参照

References

AI PLAY GUILD 本番固有の安全な接続手順、照合ルール、Discord/Mux削除手順は必要なときだけ読む:
  • AI PLAY GUILD production runbook
  • note membership handoff - LMS公開後にnote記事作成へ渡すデータ契約と検証手順
Read the AI PLAY GUILD production-specific secure connection procedures, verification rules, and Discord/Mux deletion procedures only when needed:
  • AI PLAY GUILD production runbook
  • note membership handoff - Data contract and verification procedures for handing off to note article creation after LMS publishing

分岐判断

Branch Judgment

作業開始時に、ユーザーの意図を次のどちらかに分類する。
  • LMS公開フロー: 「講義化」「公開」「LMSに上げる」「Discord通知」「Mux」「サムネを紐づける」などが目的。下の標準フローを使う。
  • note-only 分岐: 「Zoom録画を取ってきてnote記事だけ」「講義にはあげない」「LMSには出さない」「動画公開なしで記事化」などが目的。
    Zoom録画→note記事だけ分岐
    を使う。
意図が曖昧で、Convex/Mux/Discord の外部公開につながる可能性がある場合は、公開系の操作をせずに note-only として素材取得・下書き準備まで進める。
At the start of work, classify the user's intent into one of the following:
  • LMS Publishing Flow: Purpose includes "Turn into lecture", "Publish", "Upload to LMS", "Notify Discord", "Mux", "Link thumbnail", etc. Use the standard flow below.
  • note-only Branch: Purpose includes "Take Zoom recording and create only note article", "Don't upload as a lecture", "Don't publish to LMS", "Create article without video publishing", etc. Use the
    Zoom recording → note-only branch
    .
If the intent is ambiguous and could lead to external publishing via Convex/Mux/Discord, proceed with the note-only branch up to material collection and draft preparation without performing any publishing operations.

Zoom録画→note記事だけ分岐

Zoom Recording → note-only Branch

Zoom録画を取得して note記事だけ作る。LMSの動画レコード、Mux asset、Convex Storageサムネ、Discord forum投稿は作らない。
  1. 対象録画を特定する
    • ユーザーが「さっき」「今日」「昨日」など相対日時で指定した場合は、現在日付とタイムゾーンを明記して候補を出す。
    • Zoom Server-to-Server OAuth token を取得し、対象期間の cloud recordings を検索する。
    • 候補には topic、meeting ID、録画開始時刻、duration、MP4サイズ、VTT/Chat有無だけを表示する。download URL や access token は出力しない。
  2. 素材をローカルに保存する
    • 保存先は原則
      ~/Downloads/zoom-recordings/<YYYY-MM-DD-HHmm-slug>/
      。ユーザーがrepo内での保存を求めた場合は
      note-drafts/assets/<YYYY-MM-DD-slug>/
      を使う。
    • MP4、TRANSCRIPT/VTT、CHATがあれば取得し、
      recording.mp4
      transcript.vtt
      chat.txt
      metadata.json
      として保存する。
    • metadata.json
      には title候補、meeting ID、Zoom recording file ID、録画開始時刻、duration、保存ファイル、チャット有無だけを入れる。secretやtoken付きURLは入れない。
  3. 記事素材を作る
    • VTTから自然な日本語の要約、主要トピック、読者向けの学習ポイント、記事タイトル候補を作る。
    • Zoom chat がある場合は、URLや質問を抽出して記事の参考リンク・補足に反映する。URLは query、fragment、認証情報を落として扱う。
    • 必要なら
      note-drafts/handoffs/zoom-note-only-<YYYY-MM-DD-HHmm>.json
      を作り、title/date/sourceRecording/transcriptPath/chatPath/videoPath/summary/links/thumbnailPath/screenshotPathsをまとめる。
  4. note用アイキャッチとスクショを作る
    • note-only でも、原則として note用アイキャッチと本文スクショを作る。記事本文だけで投稿しない。
    • 作業用ディレクトリは
      note-drafts/assets/<YYYY-MM-DD-slug>/
      、画像は
      eyecatch.png
      screenshots/*.jpg
      に保存する。
    • MP4からスクショを抜ける環境では、VTTの重要箇所を起点に
      t-45s
      ,
      t-20s
      ,
      t
      ,
      t+20s
      ,
      t+45s
      の候補を作る。短い録画では 5秒、30%、60%、85% など実時間に合わせて候補を作る。
    • ローカルMP4の候補生成は
      ffmpeg -ss <seconds> -i recording.mp4 -frames:v 1 -q:v 2 screenshots/candidate_<seconds>.jpg
      を優先する。
      ffmpeg
      がない場合は、QuickLook等で代表サムネだけ作れるか試し、それも不可なら生成図解または公式画面キャプチャを代替にする。
    • スクショは必ず目視確認し、本文の近くの説明を支えるものだけ入れる。Zoom参加者欄、顔だけ、黒帯、関係ない画面、文字が読めない画面は使わない。
    • スクショがUI説明に合わない場合は無理に入れず、Zed/公式ドキュメント/リポジトリの画面キャプチャ、または概念図を本文画像として使う。
    • アイキャッチは note 要件に合わせて 1280:670 にする。録画スクショを使う場合は中央クロップとリサイズを行い、文字が潰れるならAI生成またはデザイン画像で作る。
    • 生成アイキャッチを使う場合は
      $imagegen
      を使い、記事テーマに沿った 1280:670 のラスター画像を作る。YouTube用の派手なLMSサムネではなく、note記事向けに読みやすいタイトル・余白・清潔感を優先する。
    • 作った
      eyecatch.png
      、採用した
      screenshots/*.jpg
      、不採用理由、画像の挿入先見出しを handoff に記録する。
  5. $note-membership-lecture
    へ引き継ぐ
    • $note-membership-lecture
      を使い、Zoom録画/VTT/Chat/summary を元に note記事を作る。
    • LMS URL や Mux playback ID は存在しないため、記事冒頭に「ハンズオンはこちら」リンクを無理に入れない。必要なら「この記事では録画内容をもとに要点と手順を整理します」のように自然な導入にする。
    • note下書き作成時は
      eyecatch.png
      をアップロードし、本文内には採用スクショを説明の近くに挿入する。画像が入ったプレビューを確認してから完了報告する。
    • LMS用サムネ生成・Convex Storage適用はしない。
    • note-only 分岐では、本文に「ここから先はメンバー向け」などの有料区切り文言を入れない。全体を無料で読める記事として構成する。
    • note-only 分岐では、ライトプラン会員アクセス、単発購入、
      limited=True
      、有料ライン設定は入れない。ユーザーが有料化を明示したときだけ
      $note-membership-lecture
      の有料設定手順に切り替える。
  6. 結果を報告する
    • 保存したMP4/VTT/Chat/metadata、eyecatch、採用スクショ、handoffのパス、記事下書きの article key、preview URL、editor URL、無料公開向けかどうか、note公開待ちかどうかを出す。
    • Convex/Mux/Discord/LMS公開を実行していないことを明記する。
Retrieve a Zoom recording and create only a note article. Do not create LMS video records, Mux assets, Convex Storage thumbnails, or Discord forum posts.
  1. Identify the target recording
    • If the user specifies relative dates like "just now", "today", or "yesterday", list candidates with the current date and time zone clearly stated.
    • Obtain a Zoom Server-to-Server OAuth token and search cloud recordings for the target period.
    • Display only the topic, meeting ID, recording start time, duration, MP4 size, and presence of VTT/Chat for candidates. Do not output download URLs or access tokens.
  2. Save materials locally
    • By default, save to
      ~/Downloads/zoom-recordings/<YYYY-MM-DD-HHmm-slug>/
      . If the user requests saving within the repo, use
      note-drafts/assets/<YYYY-MM-DD-slug>/
      .
    • Retrieve MP4, TRANSCRIPT/VTT, and CHAT (if available), and save them as
      recording.mp4
      ,
      transcript.vtt
      ,
      chat.txt
      , and
      metadata.json
      .
    • Include only title candidates, meeting ID, Zoom recording file ID, recording start time, duration, saved files, and presence of chat in
      metadata.json
      . Do not include secrets or URLs with tokens.
  3. Create article materials
    • Generate a natural Japanese summary, key topics, learning points for readers, and title candidates from the VTT.
    • If Zoom chat is available, extract URLs and questions to reflect in the article's reference links and supplements. Remove query parameters, fragments, and authentication information from URLs.
    • If necessary, create
      note-drafts/handoffs/zoom-note-only-<YYYY-MM-DD-HHmm>.json
      to compile title/date/sourceRecording/transcriptPath/chatPath/videoPath/summary/links/thumbnailPath/screenshotPaths.
  4. Create note eye-catching image and screenshots
    • Even in the note-only branch, create a note eye-catching image and body screenshots as a rule. Do not post only the article text.
    • Use
      note-drafts/assets/<YYYY-MM-DD-slug>/
      as the working directory, and save images as
      eyecatch.png
      and
      screenshots/*.jpg
      .
    • In environments where screenshots can be extracted from MP4, generate candidates at
      t-45s
      ,
      t-20s
      ,
      t
      ,
      t+20s
      ,
      t+45s
      based on key points in the VTT. For short recordings, generate candidates based on real-time positions like 5 seconds, 30%, 60%, 85%.
    • Prioritize using
      ffmpeg -ss <seconds> -i recording.mp4 -frames:v 1 -q:v 2 screenshots/candidate_<seconds>.jpg
      to generate local MP4 candidates. If
      ffmpeg
      is not available, try creating only a representative thumbnail via QuickLook, etc. If that fails, use generated illustrations or official screenshots as alternatives.
    • Always visually check screenshots and only include those that support nearby explanations in the text. Do not use Zoom participant lists, face-only shots, black bars, unrelated screens, or screens with unreadable text.
    • If screenshots do not match UI explanations, do not force them; use screenshots from Zed/official documentation/repositories or conceptual diagrams as body images.
    • Resize the eye-catching image to 1280:670 to meet note requirements. If using a recording screenshot, perform center cropping and resizing; if text becomes distorted, create it via AI generation or design images.
    • When using a generated eye-catching image, use
      $imagegen
      to create a 1280:670 raster image aligned with the article theme. Prioritize readable titles, margins, and cleanliness for note articles, rather than flashy YouTube-style LMS thumbnails.
    • Record the created
      eyecatch.png
      , adopted
      screenshots/*.jpg
      , reasons for rejection, and the heading where the image will be inserted in the handoff.
  5. Handoff to
    $note-membership-lecture
    • Use
      $note-membership-lecture
      to create a note article based on the Zoom recording/VTT/Chat/summary.
    • Since no LMS URL or Mux playback ID exists, do not force a "Hands-on here" link at the start of the article. Instead, use a natural introduction like "This article organizes key points and procedures based on the recording content" if necessary.
    • When creating the note draft, upload
      eyecatch.png
      and insert adopted screenshots near relevant explanations in the text. Confirm the preview with images before reporting completion.
    • Do not generate LMS thumbnails or apply Convex Storage.
    • In the note-only branch, do not include paywall text like "Members-only content below" in the body. Structure the entire article as freely readable.
    • In the note-only branch, do not enable Light Plan member access, one-time purchase,
      limited=True
      , or paywall settings. Switch to the paid setting procedure of
      $note-membership-lecture
      only if the user explicitly requests paid content.
  6. Report results
    • Output the paths of saved MP4/VTT/Chat/metadata, eye-catching image, adopted screenshots, handoff, article key of the draft, preview URL, editor URL, whether it is for free publishing, and whether it is pending note publication.
    • Clearly state that Convex/Mux/Discord/LMS publishing was not performed.

標準フロー

Standard Flow

  1. 入力を整理する
    • ユーザーが渡した講義リスト、既存MD、サムネ方針、対象本数、除外条件を確認する。
    • 既存まとめは
      thumbnails/summaries/lectures-for-thumbnails.md
      、1講義1ファイルは
      thumbnails/summaries/per-lecture/
      を優先する。
    • 講義タイトル、録画日、Zoom meeting ID、録画時間、Mux playback ID、サムネパス、公開URLの対応表を残す。
  2. 本番接続先を確定する
    • Vercel production env から
      NEXT_PUBLIC_CONVEX_URL
      CONVEX_DEPLOYMENT
      を取得する。
    • サイトJSに埋め込まれた Convex URL と一致するか確認する。
    • CLIが違うConvexに向く場合は
      ConvexHttpClient
      を使い、
      NEXT_PUBLIC_CONVEX_URL
      CONVEX_INTERNAL_SECRET
      で操作する。
  3. Zoom録画を探す
    • Zoom Server-to-Server OAuth token を取得し、対象期間の cloud recordings を日付範囲で検索する。
    • recording_files
      から
      MP4
      ,
      TRANSCRIPT
      /
      VTT
      ,
      CHAT
      を拾う。
    • 候補照合は、録画日、meeting ID、duration、タイトル類似度、既存MDのタイトル順で行う。
    • 既存Convexに同じ
      zoomRecordingId
      の壊れた未完成レコードがある場合だけ、重複チェック回避のため
      recordingFileId
      を渡さず新規作成する。通常は
      recordingFileId
      を渡して冪等性を保つ。
  4. 講義データを作る
    • VTTがあれば内容を読み、講義概要、学習ポイント、チャプター候補を作る。
    • Zoom chat があれば補助情報として保存し、質問やURLを概要に反映する。
    • per-lecture MDがある場合はそれを正とし、不足分だけZoomの文字起こしから補う。
  5. サムネを作る
    • 既存の指定がある場合はそのトーンを維持する。今回のAI PLAY GUILD講義サムネでは、YouTube風の大きな文字、強い輪郭、右側人物アイコン風の顔を基本にする。
    • 毎回オレンジ固定にしない。Claudeはオレンジ、Vercel/Slackは黒/紫/緑、Google/Notionは白/黒/Googleカラーなど、ツールや講義テーマに合う色にする。
    • 顔は怖くしない。目・口・髪型のバランスを自然にし、清潔感のある髪型にする。
    • 生成物は
      thumbnails/generated/lecture-thumbnails/
      に保存し、対応表MDにパスを書き戻す。
  6. Convexに投入する
    • api.zoom.createZoomManualImportVideo
      でZoom録画を動画レコード化し、Mux取り込みを起動する。
    • api.videos.updateVideoMetadataServer
      でタイトル/description/summaryを整える。
    • api.videos.generateUploadUrlServer
      でアップロードURLを作り、PNGをPUTしてから
      api.videos.setThumbnailServer
      customThumbnailStorageId
      を設定する。
    • getPublishedVideos
      では未公開動画が見えないため、Mux取り込み待ちは公開canaryまたは管理系queryで検証する。
      getZoomVideosForMigration
      はMux IDを返さない実装の可能性があるので、それだけで待機判定しない。
  7. 公開と検証をする
    • 1本目だけ
      publishVideoServer({ isPublished: true })
      で公開する。
    • getPublishedVideos
      で対象の
      muxPlaybackId
      thumbnailUrl
      が取れるか確認する。
    • 問題なければ残りを公開し、全件
      published / mux / thumbnail
      が揃うまで確認する。
    • 代表URLに
      curl
      してHTTP 200を確認する。ただし削除直後の詳細ページはアプリ側ルーティングで 200 を返すことがあるため、最終判定は公開一覧queryで行う。
  8. Discordに通知する
    • 公開時の
      discordNotify.postVideoToForum
      に任せ、数秒待つ。
    • forum channel の active threads と public archived threads を検索し、足りないタイトルだけBot APIで直接作成する。
    • 投稿本文は summary 優先、長すぎる場合は短縮し、
      https://aiplayguild.com/videos/<videoId>
      を入れる。
  9. note記事へ引き継ぐ
    • references/note-membership-handoff.md
      を読み、公開済み動画ごとのハンドオフ情報を作る。
    • ハンドオフには title/date/videoId/LMS URL/Mux playback ID/VTT/Zoom chat/summary/thumbnail/共有URL/検証結果を含める。
    • 単発1本の講義公開では、LMS公開とDiscord通知の検証後に
      $note-membership-lecture
      を自動で使い、note下書き、1280:670アイキャッチ、本文画像、有料ライン、ライトプラン会員限定設定まで進める。単発購入価格はユーザーが明示した場合だけ付ける。
    • 複数本を一括公開する場合も、ユーザーが範囲を限定していなければ各講義のnote下書きを作る。ただしnoteの公開は各記事ごとに明示確認を待つ。
    • note記事の冒頭では、動画ではなく「noteメンバーシップユーザー向けのハンズオン」として、サムネ画像を貼ってから自然なリンクを置く。
    • Zoom録画をLMS講義として公開した動画からライトプラン向けnote記事を作る場合、note用アイキャッチには必ず
      ライトプラン限定記事
      の表記を目立つ太字バッジで入れる。日本語文字が汚く見える手動オーバーレイで済ませず、必要なら
      $imagegen
      / image 2 でサムネ自体を再生成する。記事冒頭に貼るハンズオンサムネも同じ表記入り画像を使う。
  10. 結果を報告する
  • 本数、公開/未公開、Mux ready、サムネ ready、Discord投稿/skip/error、公開URLを簡潔に出す。
  • note記事を作った場合は、article key、preview URL、editor URL、有料ライン、ライトプラン、アクセスモデル、単発価格がある場合はその金額、note公開待ちかどうかを出す。
  • 途中で作った一時envファイルやsecret入りログを削除する。
  1. Organize inputs
    • Confirm the lecture list, existing MD files, thumbnail guidelines, target quantity, and exclusion criteria provided by the user.
    • Prioritize existing compilations in
      thumbnails/summaries/lectures-for-thumbnails.md
      , and per-lecture files in
      thumbnails/summaries/per-lecture/
      .
    • Maintain a correspondence table of lecture titles, recording dates, Zoom meeting IDs, recording times, Mux playback IDs, thumbnail paths, and publishing URLs.
  2. Confirm production connection destination
    • Retrieve
      NEXT_PUBLIC_CONVEX_URL
      and
      CONVEX_DEPLOYMENT
      from the Vercel production environment.
    • Confirm that it matches the Convex URL embedded in the site JS.
    • If the CLI points to a different Convex instance, use
      ConvexHttpClient
      with
      NEXT_PUBLIC_CONVEX_URL
      and
      CONVEX_INTERNAL_SECRET
      for operations.
  3. Search for Zoom recordings
    • Obtain a Zoom Server-to-Server OAuth token and search cloud recordings for the target period by date range.
    • Extract
      MP4
      ,
      TRANSCRIPT
      /
      VTT
      , and
      CHAT
      from
      recording_files
      .
    • Match candidates by recording date, meeting ID, duration, title similarity, and title order in existing MD files.
    • Only create a new record without passing
      recordingFileId
      to avoid duplicate checks if there is a broken, incomplete record with the same
      zoomRecordingId
      in existing Convex. Normally, pass
      recordingFileId
      to maintain idempotency.
  4. Create lecture data
    • If VTT is available, read the content to create a lecture overview, learning points, and chapter candidates.
    • If Zoom chat is available, save it as supplementary information and reflect questions and URLs in the overview.
    • If a per-lecture MD file exists, use it as the source and supplement missing content from the Zoom transcript.
  5. Create thumbnails
    • Maintain the existing tone if specified. For AI PLAY GUILD lecture thumbnails, base them on YouTube-style large text, strong outlines, and right-side character icon-style faces.
    • Do not fix the color to orange every time. Use colors matching the tool or lecture theme: orange for Claude, black/purple/green for Vercel/Slack, white/black/Google colors for Google/Notion, etc.
    • Do not make faces look scary. Keep the balance of eyes, mouth, and hairstyle natural, and use clean hairstyles.
    • Save generated files to
      thumbnails/generated/lecture-thumbnails/
      and write the path back to the correspondence table MD file.
  6. Import to Convex
    • Use
      api.zoom.createZoomManualImportVideo
      to convert the Zoom recording into a video record and start Mux import.
    • Use
      api.videos.updateVideoMetadataServer
      to refine the title/description/summary.
    • Use
      api.videos.generateUploadUrlServer
      to create an upload URL, PUT the PNG, then use
      api.videos.setThumbnailServer
      to set
      customThumbnailStorageId
      .
    • Since
      getPublishedVideos
      does not show unpublished videos, verify pending Mux imports via a publishing canary or admin query. Do not rely solely on
      getZoomVideosForMigration
      for waiting judgments, as it may not return Mux IDs.
  7. Publish and verify
    • Publish only the first video using
      publishVideoServer({ isPublished: true })
      .
    • Confirm that the target
      muxPlaybackId
      and
      thumbnailUrl
      can be retrieved via
      getPublishedVideos
      .
    • If no issues exist, publish the remaining videos and confirm that all have
      published / mux / thumbnail
      status.
    • Use
      curl
      on the representative URL to confirm HTTP 200. However, since the detail page may return 200 via app-side routing immediately after deletion, make the final judgment via the publishing list query.
  8. Notify Discord
    • Let
      discordNotify.postVideoToForum
      handle posting at publish time, then wait a few seconds.
    • Search active threads and public archived threads in the forum channel, and directly create missing titles via the Bot API.
    • Prioritize the summary for the post body; shorten it if too long, and include
      https://aiplayguild.com/videos/<videoId>
      .
  9. Handoff to note articles
    • Read
      references/note-membership-handoff.md
      to create handoff information for each published video.
    • Include title/date/videoId/LMS URL/Mux playback ID/VTT/Zoom chat/summary/thumbnail/shared URL/verification results in the handoff.
    • For single lecture publishing, automatically use
      $note-membership-lecture
      after verifying LMS publishing and Discord notifications, proceeding to create the note draft, 1280:670 eye-catching image, body images, paywall, and Light Plan member-only settings. Add a one-time purchase price only if explicitly specified by the user.
    • For bulk publishing of multiple videos, create note drafts for each lecture unless the user limits the scope. However, wait for explicit confirmation before publishing each note article.
    • At the start of the note article, present it as "Hands-on for note membership users" (not a video), paste the thumbnail image, then add a natural link.
    • When creating a Light Plan note article from a video published as an LMS lecture from a Zoom recording, always add a prominent bold badge stating "Light Plan Exclusive Article" to the note eye-catching image. Do not use a manual overlay that makes Japanese text look messy; regenerate the thumbnail itself via
      $imagegen
      /image 2 if necessary. Use the same image with the badge for the hands-on thumbnail pasted at the start of the article.
  10. Report results
    • Briefly output the quantity, published/unpublished status, Mux ready status, thumbnail ready status, Discord post/skip/error status, and publishing URLs.
    • If note articles were created, output the article key, preview URL, editor URL, paywall status, Light Plan status, access model, one-time price (if applicable), and whether it is pending note publication.
    • Delete temporary env files and logs containing secrets created during the process.

誤公開の削除フロー

Incorrect Publication Deletion Flow

  1. URLから
    videoId
    を抜く。
  2. getPublishedVideos
    でタイトル、Mux asset ID、Discord投稿名を確認する。
  3. Discord forum thread を active/public archived から同名検索して削除する。
  4. Mux asset ID があれば Mux API で削除する。
  5. api.videos.deleteVideoServer
    があればConvexレコードを削除する。なければ
    publishVideoServer({ isPublished: false })
    で非公開にし、削除用mutationを追加してデプロイするかユーザーに確認する。
  6. getPublishedVideos
    に対象IDが残っていないことを確認する。
  1. Extract
    videoId
    from the URL.
  2. Confirm the title, Mux asset ID, and Discord post name via
    getPublishedVideos
    .
  3. Search for the Discord forum thread by name in active/public archived threads and delete it.
  4. Delete the Mux asset via the Mux API if an asset ID exists.
  5. Delete the Convex record if
    api.videos.deleteVideoServer
    is available. If not, set it to unpublished via
    publishVideoServer({ isPublished: false })
    , then either deploy a deletion mutation or confirm with the user.
  6. Confirm that the target ID no longer appears in
    getPublishedVideos
    .

関連ファイル

Related Files

  • src/app/api/webhooks/zoom/route.ts
    - Zoom Webhook
  • src/app/api/zoom/import/route.ts
    - 単一取り込み
  • src/app/api/zoom/bulk-import/route.ts
    - 一括取り込み
  • convex/zoom.ts
    - Zoom録画レコード作成
  • convex/zoomActions.ts
    - Mux取り込み、VTT/Chat保存、AIメタデータ
  • convex/videos.ts
    - 動画公開、サムネ適用、削除系server mutation
  • convex/discordNotify.ts
    - Discord forum投稿
  • scripts/generate-thumbnail-source-md.mjs
    - サムネ用講義MD生成
  • scripts/upload-lecture-thumbnails-to-convex-prod.mjs
    - サムネ一括アップロード
  • src/app/api/webhooks/zoom/route.ts
    - Zoom Webhook
  • src/app/api/zoom/import/route.ts
    - Single import
  • src/app/api/zoom/bulk-import/route.ts
    - Bulk import
  • convex/zoom.ts
    - Zoom recording record creation
  • convex/zoomActions.ts
    - Mux import, VTT/Chat saving, AI metadata
  • convex/videos.ts
    - Video publishing, thumbnail application, deletion server mutations
  • convex/discordNotify.ts
    - Discord forum posting
  • scripts/generate-thumbnail-source-md.mjs
    - Lecture MD generation for thumbnails
  • scripts/upload-lecture-thumbnails-to-convex-prod.mjs
    - Bulk thumbnail upload to Convex production