อภิธานศัพท์
54 คำที่ใช้ในโปรเจกต์นี้ — ทุกคำมี "ค่าจริงในระบบ" กำกับ ไม่ใช่คำนิยามลอยๆ · ใช้เป็นภาษากลางเวลาคุยกับทีมและลูกค้า
ภาพใหญ่ · ธุรกิจ
ศัพท์ที่ใช้ตอนคุยกับลูกค้าและทีมขาย ยังไม่ลงรายละเอียดเทคนิค
- FAST Channelช่องฟรีมีโฆษณา
- Free Ad-Supported Streaming TV — ช่องทีวีที่ไหลต่อเนื่อง 24 ชั่วโมงบนอินเทอร์เน็ต ดูฟรี รายได้มาจากโฆษณาที่แทรกระหว่างรายการ ผู้ชมเปิดมาเจอตรงกลางรายการเหมือนทีวีบ้าน กดเลือกเรื่องเองไม่ได้ ต่างจาก YouTube หรือ Netflix ที่ผู้ชมเป็นคนเลือก
- ในระบบนี้: ทั้งระบบนี้มีไว้ตอบคำถามเดียว: คลัง YouTube ที่ลูกค้ามีอยู่ เปิดเป็นช่อง FAST ได้จริงไหม
- ดูคู่กับ: Linear · EPG
- Linearผังไหลตามเวลา
- การออกอากาศแบบไหลไปตามเวลาจริง ทุกคนที่เปิดดูพร้อมกันเห็นภาพเดียวกัน ตรงข้ามกับ VOD (Video on Demand) ที่แต่ละคนเลือกดูอะไรก็ได้เมื่อไหร่ก็ได้
- ในระบบนี้: คลิปเดียวกันบน YouTube คือ VOD · พอเอามาเรียงลงผัง 24 ชม. มันกลายเป็น Linear
- EPGผังรายการที่ผู้ชมเห็น
- Electronic Programme Guide — ตารางรายการที่โผล่บนหน้าจอผู้ชม บอกว่าตอนนี้กำลังฉายอะไรและต่อไปคืออะไร สิ่งที่ผู้ชมเห็นคือชื่อ Block ไม่ใช่ชื่อคลิปรายตัว
- ในระบบนี้: ส่งออกได้แล้วเป็นไฟล์ XMLTV ที่ `/api/epg/<studio>/<ch>/published.xml` — ปุ่ม "ส่งออก XML" บนหน้าช่อง
- ดูคู่กับ: Block · XMLTV
- Impression (โฆษณา)จำนวนครั้งที่โฆษณาถูกเห็น
- ในช่อง FAST นับแบบง่ายที่สุด: 1 เบรกที่ผู้ชม 1 คนดูอยู่ = 1 impression — ผังที่มี 4.3 เบรก/ชม. ถ้ามีคนดูเฉลี่ย 1,000 คน จะได้ราว 4,300 impressions ต่อชั่วโมง เอาไปคูณ CPM ของดีลจริงต่อได้
- ในระบบนี้: หน้าช่องคำนวณจากจำนวน Ad Slot ของวันที่เลือก ÷ 24 ชม. · เป็นตัวเลขประมาณการจากผัง ไม่ใช่ยอดวัดจริงจากเครื่องเล่น
- ดูคู่กับ: Ad Slot · Segmentation (แบ่งท่อน)
- Segmentation (แบ่งท่อน)กฎการแบ่งคลิปเป็นท่อน
- คลิปยาวถูกแบ่งเป็นท่อนเท่าๆ กันตามกฎของช่อง แล้วโฆษณาไปคั่นระหว่างท่อน — ไม่ใช่ "ผ่ากลาง" · จำนวนท่อน = ปัดใกล้สุดของ (ความยาว ÷ ท่อนละประมาณ) แล้วลดลงจนไม่มีท่อนสั้นกว่าขั้นต่ำ
- ในระบบนี้: ตั้งรายช่องที่ `/<studio>/ch/<id>/ads` · กฎเต็มอยู่ใน `10-ad-break-rules.md` (ระบบตัดคลิปจริงต้องใช้กฎเดียวกัน)
- ดูคู่กับ: Ad Slot · Slate
- Slateคลิปที่เล่นตอนเบรก
- คลิปความยาวตรงกับขนาด Ad Slot ที่เอาไว้เล่นระหว่างเบรก — ช่องหนึ่งเตรียมไว้เป็นชุดตามขนาดที่ใช้ (15 · 30 · 45 · 60 · 90 · 120 วิ)
- ในระบบนี้: ผูกลิงก์ M3U8 ต่อขนาดที่หน้า `/ads` · ขนาดที่ไม่มี slate จะเลือกเป็นเบรกไม่ได้
- ดูคู่กับ: Segmentation (แบ่งท่อน)
- Fallback fill (เติมนอกกติกา)เติมด้วยของนอกกติกาของ Block
- Block ที่ Fill Rule หาของไม่พอจะไม่ปล่อยจอดำ — ระบบคลายเงื่อนไขทีละชั้น: กองเดิมของ Block แบบไม่บังคับ evergreen → คลังทั้งช่อง → ยอมเลี่ยง Cooldown (แต่ห้ามซ้ำในวันเดียวกัน)
- ในระบบนี้: รายงานเป็น `fallbackSec` ราย Block · หน้าช่องโชว์ "เติมนอกกติกา X ชม." คู่กับ "เติมได้ 100%" เพื่อไม่ให้ตัวเลขเต็มหลอกตา
- ดูคู่กับ: Fill Rule
- Published EPGผังที่ประกาศให้ผู้ชม
- ผังระดับ Block ที่ประกาศออกไปให้ผู้ชมและพาร์ตเนอร์เห็น — บอกแค่ว่าช่วงนี้คือรายการอะไร ไม่ลงลึกถึงว่าจะฉายคลิปไหน
- ในระบบนี้: คอลัมน์ซ้ายของหน้าช่อง + ตาราง Block ท้ายหน้า · ส่งออกเป็น `published.xml` (XMLTV) ได้
- ดูคู่กับ: Block · Playout Rundown · XMLTV
- Playout Rundownแผนคลิปรายนาที
- ผลการคลี่ Fill Rule ของ Block หนึ่งออกมาเป็น Play Slot / Ad Slot จริง — เป็นแผน ยังเปลี่ยนได้จนถึงเวลาออกอากาศ (คลิปที่จะหยิบอาจยังไม่ถูกอัปด้วยซ้ำ)
- ในระบบนี้: คอลัมน์ขวาของหน้าช่อง · มีป้ายบอก 3 สถานะ: ผ่านเวลาไปแล้ว · กำลังออกอากาศ · แผน · ส่งออกเป็น `rundown.xml` ได้ (ของภายใน ห้ามส่งให้ distributor)
- ดูคู่กับ: Resolve · As-run Log
- As-run Logบันทึกสิ่งที่ออกอากาศจริง
- ของที่ออกอากาศไปแล้วจริงๆ freeze ไว้ ห้ามคำนวณใหม่ — คนละชั้นกับ Playout Rundown ที่เป็นแผน ใช้ตอบพาร์ตเนอร์/โฆษณาว่าจริงๆ แล้วอะไรออกตอนไหน
- ในระบบนี้: ยังไม่ได้ทำ — ยังไม่ล็อกอดีต · `asrun.xml` ที่ส่งออกได้ตอนนี้เป็น**ของจำลอง** สร้างจากผังตัดที่เวลาปัจจุบัน ติด simulated="true" ไว้ ห้ามเอาไปคิดสถิติ
- ดูคู่กับ: Playout Rundown · XMLTV
- XMLTVฟอร์แมตไฟล์ผังมาตรฐาน
- รูปแบบไฟล์ XML ที่วงการทีวีใช้ส่งผังกันมานาน โครงคือ `<tv>` ครอบ `<channel>` หนึ่งก้อน แล้วตามด้วย `<programme start stop channel>` ก้อนละ 1 ช่วงรายการ — distributor ฝั่งนี้ (Samsung TV Plus, AIS Playbox) รับฟอร์แมตนี้อยู่แล้ว จึงไม่ต้องขอ spec ใหม่
- ในระบบนี้: `/api/epg/<studio>/<ch>/published.xml?days=7` · 1 `<programme>` = 1 Block · เวลาใส่ offset ไทย `+0700` เสมอ · รายละเอียดใน `11-epg-delivery.md`
- ดูคู่กับ: Published EPG · EPG
- สตูดิโอStudio
- หนึ่งสตูดิโอ = หนึ่งลูกค้า = หนึ่งคลังคอนเทนต์ที่แยกขาดจากลูกค้ารายอื่น เพราะสิทธิ์คอนเทนต์เป็นของแต่ละราย ห้ามยืมคลิปข้ามกันเด็ดขาด
- ในระบบนี้: ตาราง `studios` ใน Postgres · route คือ `/<studio>` · มีเทสต์ล็อกไว้ว่าคลิปของรายหนึ่งห้ามโผล่ในผังของอีกราย
- ช่อง FASTFAST Channel ในสตูดิโอ
- ช่องทีวี 24 ชั่วโมงหนึ่งช่องที่สร้างขึ้นจากคลังของสตูดิโอนั้น จากคลังเดียวกันสร้างได้หลายช่อง เลือกส่วนผสมคนละแบบเพื่อเทียบกันว่าแบบไหนเลี้ยงตัวเองได้
- ในระบบนี้: `fastChannels` ใน `studios` · route คือ `/<studio>/ch/<id>`
โครงสร้างผัง
สามชั้นนี้คือแกนของทั้งระบบ ถ้าเข้าใจสามคำนี้ ที่เหลืออ่านออกหมด
- Schedule Templateผังแม่แบบ
- ผัง 24 ชั่วโมงหนึ่งชุดที่ใช้เป็นแบบตั้งต้นของทุกวัน ประกอบด้วย Block เรียงต่อกันจนครบ 24 ชม. ไม่มีช่องว่าง
- ในระบบนี้: ตอนนี้มีผังเดียวใช้ทุกวัน — ผังแยก วันธรรมดา/เสาร์อาทิตย์ ออกแบบไว้แล้วใน `05-daily-template-design.md` แต่ยังไม่ทำ
- Blockยังไม่เคาะคำไทย
- กล่องเวลาที่มีชื่อ เช่น 13:00–16:00 ชื่อ “Today Update” — เป็นหน่วยเดียวที่คนจัดผังต้องจัดเอง ส่วนเนื้อข้างในระบบเติมให้ตาม Fill Rule ผู้ชมเห็นชื่อ Block บน EPG ไม่ได้เห็นชื่อคลิป
- ในระบบนี้: 1 Block มี: ช่วงเวลา · ชื่อ · Fill Rule · cooldown · ตั้ง Absorbing ได้ · ตั้ง Ad ราย Block ทับค่ากลางได้
- ดูคู่กับ: Fill Rule · Absorbing Block
- Play Slotช่องคลิป
- คลิปจริงหนึ่งตัวที่ถูกวางลงในผัง ความยาวเท่ากับคลิปเป๊ะเสมอ ไม่มีการตัดให้สั้นลงและไม่มีการยืดให้เต็มช่อง
- ในระบบนี้: กติกาเหล็ก: **ห้ามตัดคลิปกลางคันทุกกรณี** เพราะเป็นปัญหาแบรนด์ของเจ้าของคอนเทนต์ ไม่ใช่แค่เรื่องความสวยงามของผัง
- Ad Slotช่องโฆษณา
- ช่องว่างสำหรับโฆษณาที่ระบบแทรกให้เอง มี 2 แบบ: เบรกคั่นระหว่างท่อนของคลิป กับเบรกท้ายคลิป (post-roll) ความยาวมาจากตารางเทียร์ของช่องนั้น
- ในระบบนี้: ตั้งรายช่องที่ `/<studio>/ch/<id>/ads` · ขนาดที่เลือกได้ = ขนาดที่มี Slate เตรียมไว้จริง
- ดูคู่กับ: Segmentation (แบ่งท่อน) · Slate · Ad Policy
- Pinned Slotคลิปที่ปักเอง
- คลิปที่คนเลือกวางเองในเวลาที่กำหนด ระบบห้ามแทนที่ ใช้กับรายการที่ต้องออกตรงเวลาแน่นอน เช่น ข่าวภาคค่ำหรือรายการสด
- ในระบบนี้: ใน Block เดียวมีทั้ง Pinned Slot และคลิปที่ระบบเติมปนกันได้ Fill Rule จะเติมรอบๆ ของที่ปักไว้
- Absorbing BlockBlock ที่ยอมหด
- Block ที่ยอมให้เวลาของตัวเองหดลงเมื่อ Block ก่อนหน้าเล่นล้นเข้ามา ผลคือมันเริ่มช้ากว่ากำหนดแต่จบตรงเวลาเดิม ทำให้ความคลาดเคลื่อนตายในบล็อกนั้น ไม่สะสมข้ามวัน
- ในระบบนี้: ทุกผังควรมีอย่างน้อย 1 อันต่อช่วง ไม่งั้นเวลาจะเลื่อนสะสมทั้งวัน — มักตั้งให้ Block กลางคืนหรือช่วงรีรันเป็นตัวรับ
- ดูคู่กับ: Drift · Overflow
- Filler Poolกองของอุดเวลา
- กองคลิปสั้นที่แยกไว้ต่างหาก ใช้เฉพาะตอนเหลือเศษเวลาท้าย Block ไม่ถูกหยิบมาเป็นคอนเทนต์หลัก เช่น โปรโมท ไฮไลต์ teaser
- ในระบบนี้: คลิปสั้นกว่า 5 นาที และ Shorts ทุกตัวถูกจัดเข้ากองนี้อัตโนมัติ (`role = filler`) — ในคลังจริงมักเกินครึ่งของคลิปทั้งหมด
- ดูคู่กับ: role
- Overflowการล้นข้าม Block
- เมื่อคลิปสุดท้ายของ Block ยาวเกินเวลาที่เหลือ ระบบเลือกปล่อยให้เล่นล้นเข้า Block ถัดไป แทนที่จะตัดคลิปทิ้ง
- ในระบบนี้: ทางเลือกสุดท้ายหลังจากลอง Filler Pool และยืด Ad Slot แล้วไม่พอ
- Driftเวลาเลื่อนสะสม
- ความคลาดเคลื่อนของเวลาจริงเทียบกับผังที่วางไว้ เกิดจากการล้นสะสมทีละนิด ถ้าไม่มีตัวดูดซับ ตอนดึกอาจเพี้ยนไปเป็นชั่วโมง
- ในระบบนี้: แก้ด้วย Absorbing Block ไม่ได้แก้ด้วยการตัดคลิป
- Ad Break (เบรกคั่นท่อน)โฆษณาคั่นกลางคลิป
- โฆษณาที่คั่นระหว่างท่อนของคลิปที่ถูกแบ่งไว้ ไม่ขัดกติกา “ไม่มี Cut” เพราะเนื้อคลิปออกครบทุกวินาที แค่แบ่งการเล่นเป็นท่อน (เลิกเรียก mid-roll ตั้งแต่ 20 ส.ค. 2026 เพราะกฎจริงคือการแบ่งท่อน ไม่ใช่การผ่ากลาง)
- ในระบบนี้: จำนวนเบรก = จำนวนท่อน − 1 · ความยาวเบรกมาจากเทียร์ของช่องนั้น
- Ad Policyตารางโฆษณา
- ตารางที่บอกว่าคลิปความยาวเท่านี้ควรแบ่งท่อนละกี่นาที เบรกคั่นกี่วินาที และท้ายคลิปกี่วินาที — ตั้งแยกต่อ **ช่อง** ไม่ใช่ต่อลูกค้า เพราะแต่ละช่องคอนเทนต์คนละแบบ
- ในระบบนี้: `adPolicy` ของช่อง (tiers + slates + minPartSec + maxStretchSec + liveBumper) · แก้ที่หน้า `/ads` ของช่องนั้น
Fill Rule · การเติมคอนเทนต์
หัวใจของระบบ — เจ้าของช่องจัดแค่ Block ที่เหลือเครื่องเติมเอง เพราะคลิปที่จะออกพรุ่งนี้ส่วนใหญ่ยังไม่ถูกอัปวันนี้
- Fill Ruleกฎการเติมคอนเทนต์
- กฎประจำ Block ที่บอกว่า “ถึงเวลานี้ ให้ไปหยิบคลิปแบบไหนมาเติม” ตั้งครั้งเดียวแล้วใช้ได้ตลอด ไม่ต้องกลับมาจัดผังใหม่ทุกวัน
- ในระบบนี้: มี 4 ชนิด และเลือกแหล่งได้จากหลายหมวด/หลาย Series พร้อมกัน (`SourceFilter` รับ `categories[]` และ `programmes[]`)
- Latest-firstเอาใหม่สุดก่อน
- หยิบคลิปที่อัปล่าสุดจากหมวดหรือช่องที่ระบุ เหมาะกับช่วงข่าวและคอนเทนต์ที่หมดอายุเร็ว
- Programme (Fill Rule)ไล่ตามตอน
- หยิบตอนของรายการประจำเรียงตามลำดับตอนที่เจ้าของจัดไว้ในเพลย์ลิสต์ ไม่ใช่เรียงตามวันอัป เหมาะกับไพรม์ไทม์และรายการที่คนรอดูต่อเนื่อง
- ในระบบนี้: ใช้คอลัมน์ `playlist_position` ที่ติดมากับ API ตอนดูด
- Evergreen rotationหมุนของไม่มีวันหมดอายุ
- สุ่มจากกองคลิปที่ไม่มีวันหมดอายุ โดยเคารพ cooldown เป็นตัวกินชั่วโมงส่วนใหญ่ของช่อง โดยเฉพาะช่วงกลางวันและดึก
- Mixedผสมหลายแหล่ง
- ผสมกฎหลายตัวตามน้ำหนักที่ตั้งไว้ ใช้กับ Block ยาวๆ ที่ไม่อยากให้โทนเดียวทั้งช่วง
- Resolveการคลี่ผังเป็นคลิปจริง
- การรัน Fill Rule ออกมาเป็น Play Slot จริง เกิดตอนใกล้ออกอากาศ ไม่ใช่ตอนวางผัง เพราะคลิปที่กฎจะดึงมักยังไม่มีอยู่ตอนวางผัง
- ในระบบนี้: ระบบ resolve ล่วงหน้า 28 วัน (horizon) แล้วเดินต่อทุกวัน
- Cooldown (cooldownDays)ระยะห่างก่อนฉายซ้ำ
- คลิปเดิมต้องเว้นอย่างน้อยกี่วันก่อนกลับมาออกซ้ำ ตั้งราย Block และนับข้ามวันได้ นี่คือปุ่มที่ทีมจะปรับบ่อยที่สุด
- ในระบบนี้: สั้น → เติมผังได้เต็มแต่คนดูเจอของซ้ำบ่อย · ยาว → ของสดกว่าแต่ถ้าคลังไม่พอจะเกิดช่องโหว่ · simulator มีไว้ให้เห็น trade-off นี้เป็นตัวเลขก่อนตัดสินใจ
- Horizonระยะที่คลี่ผังล่วงหน้า
- จำนวนวันที่ระบบคลี่ผังไว้ล่วงหน้า ใช้เป็นฐานคำนวณเมตริกทุกตัว ถ้าวัดจากวันเดียวจะไม่เห็นการซ้ำ
- ในระบบนี้: 28 วัน
- Deterministicผลลัพธ์คงที่
- ใส่ข้อมูลชุดเดิมแล้วต้องได้ผังเดิมเป๊ะทุกครั้ง ถ้าสุ่มใหม่ทุกรอบจะเทียบสองทางเลือกไม่ได้เลย เพราะไม่รู้ว่าตัวเลขที่ต่างกันมาจากการตั้งค่าหรือมาจากการสุ่ม
- ในระบบนี้: seed + คลัง + rule เดิม → ผังเดิม (`src/engine/rng.ts`)
- Repeat factorความถี่การฉายซ้ำ
- คลิปหนึ่งถูกเล่นซ้ำกี่ครั้งใน horizon และครั้งที่ใกล้กันที่สุดห่างกันกี่วัน ตัวเลขนี้บอกว่าคลังพอหรือไม่พอตรงๆ
- Fill completenessเติมผังได้กี่เปอร์เซ็นต์
- แต่ละ Block เติมเวลาได้กี่ % ของที่ควรจะเป็น และ Block ไหนขาดเป็นประจำ ใช้ชี้ว่าต้องผลิตคอนเทนต์เพิ่มตรงช่วงไหน
- ลองผังนี้คลี่ผังที่ยังไม่บันทึก
- ในโหมดแก้ผัง กดแล้วคลี่ผังที่กำลังแก้ 7 วันด้วยคลังและ seed ชุดเดิม เพื่อเทียบตัวเลขกับผังที่บันทึกไว้ก่อนเคาะ — ผังจริงไม่ถูกแตะจนกว่าจะกดบันทึก
- ในระบบนี้: `/<studio>/ch/<id>?edit=1` · `simulateBlocks()` ใน `src/lib/preview.ts`
ป้ายกำกับคลิป
คลิปหนึ่งตัวมีป้าย 3 แกนที่ไม่เกี่ยวกัน — ถ้ายัดรวมเป็นป้ายเดียวจะตีกันทันที เช่น ข่าวรายวันคือของที่หมดอายุเร็วแต่เป็นรายการหลัก ส่วนไฮไลต์ที่ตัดมาคือของไม่มีวันหมดอายุแต่เป็นแค่ของอุดเวลา
- kindชนิดของไฟล์
- คลิปนี้เป็นของแบบไหนตั้งแต่ต้นทาง — `normal` คลิปแนวนอนปกติ · `short` คลิปแนวตั้ง (หรือสั้นไม่เกิน 60 วินาที) · `live` ไฟล์ไลฟ์ย้อนหลัง
- ในระบบนี้: ตรวจจากสัดส่วนภาพที่ YouTube ให้มา และการมี `liveStreamingDetails` · Shorts ขึ้นจอ 16:9 ได้แต่ต้องมีขอบดำหรือพื้นหลังเบลอ · Live archive มักยาวและมีช่วงรอก่อนเริ่ม ปกติไม่เอาเข้าผัง
- roleบทบาทในผัง
- คลิปนี้ใช้เป็นตัวชูโรงหรือใช้อุดเวลา — `programme` คือรายการหลักที่เป็นแกนของ Block ส่วน `filler` คือของอุดเศษเวลาท้าย Block เท่านั้น
- ในระบบนี้: คำนวณเองจากความยาว ไม่ต้องพึ่ง LLM ไม่มีค่าใช้จ่าย: **สั้นกว่า 5 นาที หรือเป็น Shorts → filler** ที่เหลือเป็น programme (`FILLER_MAX_SEC = 300` ใน `src/lib/store.ts`)
- ดูคู่กับ: Filler Pool
- Shelf lifeอายุใช้งาน
- นับจากวันอัปโหลด คลิปนี้ยังฉายได้อีกกี่วัน ค่าที่เอนจินใช้จริงเป็นตัวเลขวัน ส่วนป้ายเป็นแค่ชื่อเรียกช่วง มี 3 ระดับพอ ไม่เอาละเอียดกว่านี้เพราะ LLM สับสนระหว่างระดับที่ใกล้กัน
- ในระบบนี้: `evergreen` ไม่มีวันหมดอายุ (null) · `topical` 30 วัน · `daily` 7 วัน · คลิปที่ยังไม่เคยผ่าน Autopilot เป็น null ไปก่อน (ถือว่าไม่หมดอายุ แต่ไม่ใช่ค่าที่ยืนยันแล้ว)
- เลยอายุแล้วexpired
- คลิปที่วันอัปโหลดบวกอายุใช้งานแล้วเลยวันนี้ไปแล้ว คลิปยังอยู่ในคลังไม่ได้หายไปไหน แต่ Fill Rule จะไม่หยิบไปลงผัง ข่าววันนี้จึงหลุดออกจากผังเองในวันที่ 8 โดยไม่ต้องมีใครไปลบ
- ในระบบนี้: คำนวณสดทุกครั้งจากวันอัป ไม่เก็บเป็นธง เพราะธงจะเน่าทุกเที่ยงคืน · เห็นตัวเลขได้ที่ checkbox บนแถบตัวกรองหน้าคลัง
- หมวดหมู่Category
- คำที่บอกว่าคอนเทนต์กลุ่มนี้เป็นประเภทเดียวกัน เช่น “ข่าวเศรษฐกิจ” “รีวิวอุปกรณ์” — Fill Rule ของแต่ละ Block หยิบคลิปจากหมวดที่ระบุไว้ Block หนึ่งจึงมีรสชาติเดียวกันตลอดช่วง
- ในระบบนี้: หมวดเป็นของแต่ละสตูดิโอเอง ไม่ใช้ร่วมกัน · **อายุใช้งานผูกกับหมวด** แก้ที่หมวดแล้วคลิปทั้งกองเปลี่ยนตาม · แก้ได้ที่ `/<studio>/categories`
- Seriesรายการประจำ
- รายการที่ออกเป็นตอนๆ เช่น “Talk ลงทุนแมน” ใช้เป็นแกนของ Fill Rule แบบไล่ตอน และเป็นหน่วยที่ Autopilot ใช้ตัดสินหมวด/อายุใช้งาน (ยิงทีละกอง ไม่ใช่ทีละคลิป ค่าใช้จ่ายจึงคงที่)
- ในระบบนี้: มาได้ 2 ทาง: (1) ชื่อเพลย์ลิสต์ที่เจ้าของจัดไว้ ติดให้ตอนดูด (2) อ่านข้อความหลัง `|` ตัวสุดท้ายของชื่อคลิป แล้วให้คนกดยืนยันที่ `/<studio>/series` — ไม่ได้ใช้ LLM
- derivedFromตัดมาจากคลิปไหน
- ไฮไลต์หรือคลิปสรุปที่ตัดมาจากคลิปเต็ม กติกาที่ตั้งใจไว้คือถ้าต้นฉบับอยู่ในคลังให้เลือกต้นฉบับก่อนเสมอ และห้ามฉายไฮไลต์ใกล้ต้นฉบับ
- ในระบบนี้: **คอลัมน์มีใน DB แล้วแต่ยังไม่มีตัวจับคู่อัตโนมัติ** ต้องเทียบชื่อ/ความยาว — รอทำตอนเจอเคสจริงว่ากวนผัง
การดูดคลิปจาก YouTube
ระบบไม่ได้เก็บไฟล์วิดีโอ เก็บแต่ metadata (ชื่อ · ความยาว · วันอัป · เพลย์ลิสต์) ไฟล์จริงยังอยู่บน YouTube — ส่วนนี้คือกติกาว่าคลิปไหนได้เข้าคลัง
- Ingest Rulesกฎการดูดคอนเทนต์
- ชุดกฎที่บอกว่าจะเอาคลิปไหนจากช่อง YouTube หนึ่งเข้าคลัง เดินจากบนลงล่าง **กฎแรกที่รับคลิปไว้เป็นเจ้าของคลิปนั้น** และเป็นตัวตั้งชื่อ Series ให้ — แก้ปัญหาคลิปเดียวอยู่หลายเพลย์ลิสต์ โดยให้ลูกค้าเป็นคนเรียงว่าเพลย์ลิสต์ไหนสำคัญกว่า
- ในระบบนี้: **กฎแยกรายช่อง YouTube เสมอ** ช่องข่าวรายวันกับช่องสารคดีของเครือเดียวกันใช้กฎคนละแบบ · ดูกฎที่ตั้งไว้ได้ที่ `/<studio>/settings`
- uploads playlistคลิปทั้งช่อง
- เพลย์ลิสต์พิเศษที่ YouTube สร้างให้ทุกช่องอัตโนมัติ รวมคลิปทั้งหมดของช่องเรียงจากใหม่ไปเก่า เป็นแหล่งเดียวที่รับประกันว่าเรียงตามวันที่
- ในระบบนี้: เพราะเรียงตามวันที่แน่นอน ระบบจึง **หยุดสแกนกลางคันได้** เมื่อพ้นกรอบเวลา ซึ่งเป็นวิธีเดียวที่ลดโควตาได้จริง
- withinDaysย้อนหลังกี่วัน
- เอาเฉพาะคลิปที่อัปภายใน N วันล่าสุด ใช้คุมว่าอะไรได้เข้าคลัง
- ในระบบนี้: **ประหยัดโควตาเฉพาะกับ uploads เท่านั้น** — เพลย์ลิสต์ธรรมดาเรียงตามที่เจ้าของจัด ไม่ได้เรียงตามวัน จึงต้องเปิดครบทุกหน้าก่อนถึงจะรู้ว่าคลิปไหนอยู่ในกรอบ
- maxClipsเพดานคลิป
- หยุดเมื่อได้ครบ N คลิป ใช้กับเพลย์ลิสต์ใหญ่ที่ไม่ได้อยากได้ทั้งกอง
- ในระบบนี้: **หยุดสแกนได้จริง = ประหยัดโควตา** แต่ N คลิปแรกนับตามลำดับที่เจ้าของจัดไว้ ไม่ใช่ตามวันที่เสมอไป
- ownChannelOnlyตัดคลิปช่องอื่นทิ้ง
- เพลย์ลิสต์ใส่คลิปของช่องอื่นได้ ซึ่งลูกค้าไม่มีสิทธิ์เอาไปออกอากาศ ระบบจึงตัดทิ้งเสมอและรายงานว่าตัดไปกี่คลิป
- ในระบบนี้: เปิดเป็นค่าเริ่มต้นทุกกฎ
- โควตาquota units
- งบการเรียก YouTube Data API ต่อวัน การเปิดดูรายการคลิป 1 หน้า (50 คลิป) คิด 1 หน่วย การขอรายละเอียดคลิป 50 ตัวก็คิด 1 หน่วย
- ในระบบนี้: บัญชีฟรีได้ **10,000 หน่วยต่อวัน** · หน้าจอแสดงประมาณการก่อนกดดูดทุกครั้ง
- หาคลิปใหม่poll
- การสแกนเบาๆ เพื่อดูว่ามีคลิปใหม่ถูกอัปหรือยัง เปิด uploads playlist จากบนสุดแล้วหยุดเมื่อถึงคลิปที่เก่ากว่าคลิปใหม่สุดที่มีในคลังอยู่แล้ว **ไม่ลบอะไรทั้งนั้น**
- ในระบบนี้: cron ยิงทุก 2 ชั่วโมง (`/api/cron/poll`) · ปกติ **1 หน่วยโควตาต่อช่อง** · ใช้วันอัปเป็นเส้นหยุด ไม่ใช่ “รู้จัก id นี้ไหม” เพราะคลิปที่ถูกกรองทิ้งอย่าง Shorts จะไม่มีวันเข้าคลัง แล้วจะสแกนไม่จบสักที
- ซิงก์เต็มตามกฎreingest
- รันกฎทั้งชุดใหม่ทั้งหมด ได้คลิปใหม่ที่เข้ากฎ **และลบคลิปที่ไม่เข้ากฎแล้วออกจากคลัง** (ลูกค้าถอดออกจากเพลย์ลิสต์ หรือพ้นกรอบเวลาไปแล้ว) เพราะคลังต้องตรงกับกฎเป๊ะ ไม่มีของค้าง
- ในระบบนี้: **ยังต้องกดเอง ไม่ให้ cron ทำ** เพราะต้องกันคลิปที่เคยออกอากาศไปแล้วไม่ให้ถูกลบก่อน ไม่งั้นประวัติออกอากาศจะพัง
ระบบและเครื่องมือ
ศัพท์ฝั่งเทคนิคที่โผล่บ่อยเวลาคุยกันในทีม
- Autopilotตัวช่วยเสนอผัง
- การยิง LLM หนึ่งครั้งตอนสร้างช่อง FAST ด้วย “สารบัญคลัง” ระดับกอง (ช่อง YouTube × Series) ไม่ใช่รายคลิป ได้กลับมา 2 อย่าง: หมวดและอายุใช้งานของแต่ละกอง กับผัง 24 ชั่วโมงพร้อมเหตุผลราย Block
- ในระบบนี้: ยิงระดับกองเพราะคลิปมีเป็นพันแต่กองมีไม่กี่สิบ ค่าใช้จ่ายจึงคงที่ · ใช้เวลา 40–60 วินาที · ตรวจคำตอบด้วย schema ถ้าเพี้ยนลองใหม่อัตโนมัติ 1 ครั้ง
- metadataข้อมูลกำกับคลิป
- ข้อมูลรอบตัวคลิปที่ไม่ใช่ตัวไฟล์วิดีโอ — ชื่อ ความยาว วันอัปโหลด เพลย์ลิสต์ที่สังกัด ทั้งระบบนี้ทำงานด้วย metadata ล้วน
- ในระบบนี้: นี่คือประเด็นหลักของ `06-warp-architecture.md`: จัดผัง 24 ชม. × 28 วันได้โดยไม่ต้องมีไฟล์วิดีโอสักไฟล์ ไฟล์จริงค่อยดูดมาเฉพาะคลิปที่จะออนแอร์
- resolve engineแกนคำนวณผัง
- โมดูลที่รับผัง + คลัง + กฎ แล้วคืนผังจริงรายวันพร้อมเมตริก เป็นส่วนเดียวของระบบที่มีชุดทดสอบครบ
- ในระบบนี้: `src/engine/` · เทสต์ 32 เคส ครอบคลุมทั้ง 7 เคสบังคับใน PRD รวมเคสที่ล็อกว่าคลังของแต่ละลูกค้าห้ามปนกัน