lucian.solutions/blog/


แงะ Streamlabs API จนออกมาเป็น Twitch Chat Overlay ให้ใช้



Categories / ประเภท

Personal

Tweet Share https://lucian.solutions/blog/tw-custom-chat-overlay

สวัสดีครับ จารย์กานต์ Sir Lucian ครับผม

สำหรับโปรเจคนี้ก็ได้พัฒนามาซักพักใหญ่ๆแล้วล่ะครับ แค่ยังไม่ได้มีเวลาว่างมาเขียน Documentation หรือ Blogpost จนกระทั่งวันนี้! เราจะมานำเสนอนวัตกรรมเขียนเอง งมเอง Suffer เอง และเฮฮาสังสรรค์ไปด้วยกันกับสิ่งที่เรียกว่า Twitch Chat Overlay กันนะครับ

สำหรับคนที่ยังไม่คุ้นชินกับเหล่าสตรีมเมอร์ ไม่ว่าจะเป็น Platform ไหนนะครับ สตรีมเมอร์มักจะเพิ่ม Live Chat ลงไปในหน้าสตรีมของเขา ซึ่งช่องที่เขาใส่ใจรายละเอียดหรืออยากให้มันเข้ากับธีมช่อง เขาก็จะดัดแปลงช่องการแสดงแชทนี้ให้เข้าธีมครับ ไม่ว่าจะเป็นการปรับรูปลักษณ์ ลูกเล่นต่างๆ ให้เหมาะสม บางคนก็แนวน่ารักบางคนก็ Edgy หรือสายมีมก็มีให้เห็นครับ

และด้วยความที่สตรีมเมอร์เพื่อนบ้านของผมหลายๆคนก็ยังใช้ของ Stock ที่เป็น Text เปลือยๆ เห็นแล้วก็น่ากำหมัดเล็กน้อยที่ไม่น้อย ประจบกับผมต้องการหาโปรเจค dev มาหาทำนอกงานประจำที่ไม่ใช่งานวาด ก็เลยเกิดเป็นโปรเจคนี้ขึ้นมาครับ

ทีนี้ เรามาดูสเต็ปต่างๆที่ต้องเตรียมการกันก่อน Suffer นะครับ อย่างแรกเลยคือ การตรัสรู้ว่า API Streamlabs มันส่งอะไรมาบ้าง สาเหตุที่ผมใช้ของ Streamlabs ก็เพราะผมใช้ Chat Overlay ตัวดั้งเดิมของมันอยู่แล้ว เลยเอามาต่อยอดให้สุดครับ แต่มันติดปัญหาที่ว่า ผมพลิกแผ่นดิน พลิกมหาสมุทรหา Documentation ของ Streamlabs API ก็หาไม่เจอครับ แบบว่า ไม่จริงน่า! ระบบที่คนใช้ก็ตั้งเยอะ แต่ไม่มี Documentation เลยเนี่ยนะ บ้าไปแล้ว 💀 แล้วผมก็กุมขมับไปวันนึงเต็มๆ จนกระทั่งผมสังเกตบรรทัดนึงในโค้ด Javascript ของ Default Chat Overlay ของ Streamlabs ครับว่า

document.addEventListener('onEventReceived', function(obj) {});

ทันใดนั้นครับ ผมก็มีความคิดที่ว่า ถ้าเรา console.log(obj); มาทั้งก้อน มันจะออกมายังไงหว่า เท่านั้นแหละครับ ออกมาทั้ง JSON Object แบบ บอกหมดเลยว่ามี Parameters อะไรให้ใช้บ้าง ความรู้สึกแรกเลยคือ โย่ว เสร็จชั้นล่ะ

แต่เอาจริงๆทั้งก้อนมันก็เยอะกว่าที่ต้องการแหละครับ ทีนี้เรามาดูกันดีกว่าว่า ตัวที่เราจำเป็นต้องใช้มีอะไรบ้าง ตัวอย่างนี้จะเป็นของแชทสลับข้างนะครับ โดยที่ Streamer และ Mod จะอยู่ชิดซ้าย Role อื่นๆจะอยู่ชิดขวาครับ ส่วนแบบอื่นๆอีกสองแบบเดี๋ยวกล่าวอีกทีนะครับ

  • obj.detail.messageId // String, แต่ละข้อความจะมี Unique ID
  • obj.detail.subscriber // Boolean, เช็คว่าผู้แชทเป็น Subscriber หรือไม่
  • obj.detail.tags.vip // String (0 or 1), เช็คว่าผู้แชทเป็น VIP ของช่องหรือไม่
  • obj.detail.tags.mod // String (0 or 1), เช็คว่าผู้แชทเป็นดาบ (Moderator) ของช่องหรือไม่
  • obj.detail.owner // Boolean, เช็คว่าผู้แชทเป็นเจ้าของหรือไม่
  • obj.detail.tags.color // String, สีชื่อของผู้แชท

ซึ่ง Parameters ต่างๆนี้ เราสามารถเอามาใช้ให้กรอบคำพูดแชทแยกตาม Role ของช่องได้ครับ

CSS

อย่างเช่นตัวพื้นฐานที่ผมทำมาก็จะมี Streamer พื้นสีแดง, Mod พื้นสีเขียว, VIP พื้นสีชมพู, Sub พื้นสีขาว (ซึ่งต้องทำให้ Text เป็นสีดำแทน โดยแก้สีฟอนต์ที่ .username_box_sub ครับ), ผู้แชทธรรมดา พื้นสีดำ ตาม Class ในไฟล์ CSS โดยสัญลักษณ์บอก Class คือจุด . ครับ - .wrapper-streamer, .wrapper-mod, .wrapper-vip, .wrapper-sub ผู้แชทธรรมดา จะเป็นแค่ .wrapper ครับ

สำหรับในส่วน .wrapper-role:before หรือ .wrapper-role:after นี่ก็จะเป็นส่วนที่เป็นติ่งสามเหลี่ยมหน้าหรือหลังกล่องที่แสดงข้อความครับ ถ้าเปลี่ยนสีพื้น Role ไหนก็อย่าลืมเปลี่ยนตรงนี้ตาม Role ด้วยนะครับ

ในส่วนของ Badge ผมได้ใส่ไว้อยู่ทั้งหมด 2 ตำแหน่งในกล่องข้อความหนึ่งกล่อง แล้วใช้วิธีปิด Class และการแสดงผลตาม Role ครับ จะเป็นมุมซ้ายและขวาบนของกล่องนะครับ


Javascript

สำหรับในส่วนของ Javascript นะครับ หรือที่ทุกคนพอจะนึกภาพได้ว่าตรงนี้แหละ คือ True Coding/Programming เป็นส่วนของ การทำงานใช้ Logic นะครับ ซึ่งในส่วนของการอัพเดตแชทแบบ Real Time ก็คือ ให้ตรวจจับตามอัพเดทแชท หรือบรรทัดที่เขียนว่า document.addEventListener('onEventReceived', function(obj) {}); นะครับ โดยในวงเล็บปีกกา {} ก็จะเป็นชุดคำสั่งว่า เราจะต้องทำอะไรกับข้อมูลบ้างทุกครั้งที่แชทอัพเดตนะครับ

ขั้นแรกคือการแปะ ID ตามกล่องครับ โดยจะมีการแปะที่ตัวกล่อง ชื่อผู้แชท และข้อความของผู้แชท เพื่อจำแนก ว่าข้อความนี้ต้องใช้ข้อมูลอะไรในการเปลี่ยนการแสดงผลต่อไป ตามนี้

  • var messageID = obj.detail.messageId+'-wrapper'; // แปะ ID ที่กล่องข้อความ
  • var messageFrom = obj.detail.messageId+'-username-box'; // แปะ ID ที่ชื่อผู้แชท
  • var messageBody = obj.detail.messageId+'-message-box'; // แปะ ID ที่ข้อความแชทในกล่อง

เสร็จแล้วก็จะเป็นการดึง Role ของผู้แชทจาก JSON มาเก็บไว้ให้เช็คต่อง่ายๆครับ

  • var isSub = obj.detail.subscriber;
  • var isVIP = obj.detail.tags.vip;
  • var isMod = obj.detail.tags.mod;
  • var isStreamer = obj.detail.owner;

จากนั้นก็จะเป็นการเช็ค if-else ตาม Role เลยครับ เรียกจาก if แรกที่เป็นเจ้าของช่อง else if ที่เป็น Mod, VIP, Sub และปิดท้ายด้วย else ผู้แชททั่วไปครับ ขอยกตัวอย่างการเช็คว่าเป็น Subscriber ในแชทสลับด้านแล้วกันนะครับ

else if (isSub) { // Subscriber
    var elementWrapper = document.getElementById(messageID);
    elementWrapper.classList.add("wrapper-sub");
    elementWrapper.classList.remove("wrapper");

อันแรกก็จะเป็นการดึงกล่องที่ถูกต้องจาก ID ที่เราแปะไว้นะครับ โดยการใช้ document.getElementById(messageID); เราก็จะได้เลือกกล่องนั้นมาสลับใส่ Class ที่ถูกต้องตาม Role โดยการเพิ่ม elementWrapper.classList.add("wrapper-sub"); และลบ Class elementWrapper.classList.remove("wrapper"); ครับ

    if (obj.detail.tags.hasOwnProperty('color')) {
        elementWrapper.style.borderRightColor = obj.detail.tags.color;
    }
    else {
        elementWrapper.style.borderRightColor = 'white';
    }

จากนั้นจะเป็นการดึงข้อมูลสีชื่อผู้แชท obj.detail.tags.color มาใส่ที่ขอบครับ โดยใช้การเช็คว่าถ้ามีสีก็จะใช้ค่าสีครับ if (obj.detail.tags.hasOwnProperty('color')) ซึ่งในกรณี Subscriber นี้จะอยู่ทางขวา ก็จะใช้การเปลี่ยนสีขอบที่กล่องตามนี้ครับ elementWrapper.style.borderRightColor = obj.detail.tags.color;

ถ้าไม่สามารถดึงข้อมูลได้ก็จะใช้สีขาวตาม else นั่นเอง

    document.getElementById(obj.detail.messageId+'-d-none-right-inv').style.display = "none";
    document.getElementById(obj.detail.messageId+'-d-none-right-top').style.display = "none";
    document.getElementById(obj.detail.messageId+'-meta').style.textAlign = "right";
    document.getElementById(obj.detail.messageId+'-message-box').style.textAlign = "right";

ต่อไปจะเป็นการปิดการแสดงผล badge ในข้างที่ผิดนะครับ เนื่องจากเราได้วาง badge ไว้ทั้งสองข้างใน HTML เราจึงต้อง ทำการใส่ .style.display: "none"; ในด้านที่ผิดครับ เช่น กล่อง Sub ชิดขวา ก็ต้องปิดขวาให้แสดงผลแต่ซ้าย โดยใช้ .style.textAlign = "right"; ครับ

อีกสิ่งที่ต้องทำคือจัด text-align ให้ชิดซ้ายชิดควาตามด้านครับ อย่างอันนี้ก็เป็น .style.textAlign = "right";

    var elementFrom = document.getElementById(messageFrom);
    elementFrom.classList.add("username_box_sub");
    elementFrom.classList.remove("username_box");
    var elementBody = document.getElementById(messageBody);
    elementBody.classList.add("message_box_sub");
    elementBody.classList.remove("message_box");
}

ส่วนสุดท้าย เป็นเรื่อง optional ของสีพื้นกล่องสีกว่าที่ต้องปรับให้สีฟอนต์เป็นสีเข้มครับ เหมือนเดิมครับ เพิ่ม-ลบ Class

โดยที่ผลสุดท้ายก็จะออกมาเป็นตามที่เห็นคล้ายๆด้านล่างเลยครับ แล้วก็เป็นชิดขวาทั้งหมด

สำหรับ Release 1.0 นี้ ผมได้จัดเตรียมไว้ให้สามแบบครับ

  1. ชิดซ้าย twitch-chat-left
  2. ชิดขวา twitch-chat-right
  3. สลับซ้ายขวา (สตรีมเมอร์และ Mod อยู่ซ้าย คนอื่นอยู่ขวา) twitch-chat-alt

โดยที่วิธีใช้ก็คือสามารถ Copy Paste ไปวางช่อง HTML, CSS, Javascript ได้เลยครับ แล้วผมก็แถมด้วยสไตล์ที่ผมใช้เองด้วย lucian-chat ใครอยากเอาไปใช้ก็ ตามสะดวกเลยครับ ลิงก์เชิญไปที่

GitHub Repository


หรือใครอยากจะมาให้ผมดัดแปลงอะไรนิดหน่อยเพื่อคุณก็สามารถจ้างได้นะครับ คิดค่าบริการเริ่มต้นที่

500 บาท/Custom Made

*เพิ่มตามความซับซ้อนสำหรับคนที่ไม่อยากปวดหัวกับการแงะโค้ด 😂


อย่างไรก็ดี ก็ขอให้สตรีมเมอร์ทุกท่านมีความสุขกับการสตรีมนะครับ วันนี้มีเพียงเท่านี้ ใครมีคำถามอยากไปแงะเองก็สอบถามได้ตามช่องทางติดต่อต่างๆนะครับ

Farewell, lads and lassies.

© 2022- Lucian Solutions, Karn Lucian Kamolnavin (Sir Lucian)