อภิธานศัพท์

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 รวมเคสที่ล็อกว่าคลังของแต่ละลูกค้าห้ามปนกัน