Paxa Labs

บทความText-to-Speech

ภาษาไทยไม่มีจุดจบประโยค: เสียงพูดแบบสตรีมควรตัดตรงไหน

ภาษาไทยจบประโยคด้วยการเว้นวรรคโดยไม่มีจุด ระบบเสียงที่สตรีมข้อความไปยังซ็อกเก็ตสังเคราะห์เสียงจึงต้องตัดสินใจเองว่าประโยคจบตรงไหน ก่อนที่เสียงจะเริ่มพูดได้

· อ่าน 2 นาที

ภาษาไทยจบประโยคด้วยการเว้นวรรค วรรคเดียวกันนี้ยังใช้แบ่งวลีในประโยค และงานเขียนทั่วไปไม่มีจุดปิดท้าย ระบบเสียงที่สตรีมคำตอบไปยังซ็อกเก็ตสังเคราะห์เสียงระหว่างที่โมเดลภาษายังเขียนอยู่ จึงต้องตัดสินใจเองว่าประโยคหนึ่งจบตรงไหนและประโยคถัดไปเริ่มตรงไหน อักขระที่โค้ดภาษาอังกฤษรอ ไม่มีวันมาถึงในภาษาไทย

บทความนี้ว่าด้วยการตัดสินใจนั้น ครอบคลุมว่าซ็อกเก็ตแบบ liveทำอะไรกับสตรีมข้อความภาษาไทย คำตอบภาษาไทยมีจุดตัดแบบไหนให้ใช้ ตัดตรงไหนแล้วฟังผิด และวิธีให้โมเดลภาษาทำเครื่องหมายจุดตัดให้เอง

การเว้นวรรคทำหน้าที่แทนจุด#

ภาษาไทยเขียนใช้อักขระเดียวทำสองหน้าที่ วรรคปิดประโยค และวรรคก็แบ่งวลีในประโยคด้วย จุลภาคพบในตัวเลขและรายการ เครื่องหมายคำถามพบในแชตมากกว่าในสิ่งพิมพ์ ส่วนจุดพบหลังคำย่อและแทบไม่พบที่อื่น ผู้อ่านแยกวรรคจบประโยคจากวรรคแบ่งวลีได้จากคำที่อยู่สองข้างของวรรคนั้น

หลักการเว้นวรรคที่เรียนกันในโรงเรียนระบุตำแหน่งของวรรคไว้ คือหลังประโยคที่สมบูรณ์ หน้าคำสันธานอย่าง แต่ หรือ เพราะ รอบตัวเลขและข้อความในเครื่องหมายคำพูด และระหว่างรายการแต่ละข้อ ย่อหน้าที่เขียนดีคือสายของวลีสั้น ๆ ที่เว้นวรรคต่อกัน และจุดจบประโยคในสายนั้นไม่มีเครื่องหมายของตัวเอง

เรื่องนี้กลายเป็นปัญหาทันทีที่ข้อความถูกอ่านออกเสียงระหว่างที่กำลังมาถึง โค้ดสตรีมภาษาอังกฤษรอจุด โค้ดสตรีมภาษาไทยไม่มีอะไรให้รอ

ทำไมจุดตัดจึงกำหนดความหน่วง#

ระบบเสียงแบบ live ส่งข้อความไปยังซ็อกเก็ตทันทีที่โมเดลภาษาผลิตออกมา และซ็อกเก็ตสังเคราะห์เสียงเป็นช่วง ๆ ช่วงหนึ่งเริ่มเมื่อบัฟเฟอร์มีข้อความที่คุ้มจะพูด ผู้ฟังได้ยินช่วงแรกหลังจากโมเดลเขียนประโยคแรกเสร็จบวกเวลาสังเคราะห์หนึ่งรอบ และทุกจุดตัดหลังจากนั้นคือจังหวะที่เสียงหยุดหายใจ

จุดตัดที่ผิดทำให้เกิดปัญหาสองแบบ ช่วงที่ตัดเร็วเกินไปจะพูดวลีครึ่งเดียว หยุด แล้วพูดส่วนที่เหลือด้วยระดับเสียงที่ตั้งต้นใหม่ ฟังเหมือนพูดตะกุกตะกัก ช่วงที่ตัดช้าเกินไปจะรอข้อความที่โมเดลยังเขียนไม่เสร็จ และความเงียบก่อนคำแรกยาวขึ้นตามทุกตัวอักษรที่โมเดลเติมเข้ามา

ซ็อกเก็ตจะสังเคราะห์เสียงอัตโนมัติเมื่อเจอสัญญาณสามอย่าง คือขึ้นบรรทัดใหม่ในเฟรม เครื่องหมายจบประโยคที่ท้ายบัฟเฟอร์ หรือความยาวบัฟเฟอร์ถึงเกณฑ์ บทสนทนาภาษาอังกฤษเข้าเงื่อนไขที่สองทุกครั้งที่เจอจุด บทสนทนาภาษาไทยไม่เข้าสองเงื่อนไขแรกเลย และต้องอาศัยเกณฑ์ความยาว ซึ่งเหมาะกับย่อหน้าแต่มาช้าเกินไปสำหรับคำตอบประโยคเดียว เอกสารอ้างอิง APIอธิบายสัญญาณทั้งสามและเฟรม flush ที่สั่งสังเคราะห์เสียงด้วยตัวเอง

ประโยคภาษาไทยในบทสนทนาจบตรงไหน#

ภาษาพูดบอกจุดจบของถ้อยคำชัดกว่าภาษาเขียน คำตอบจากผู้ช่วยจบด้วยคำลงท้ายบ่อยกว่าย่อหน้าร้อยแก้วมาก ครับ และ ค่ะ ปิดประโยคบอกเล่าแบบสุภาพ คะ และ ครับ ปิดคำถามแบบสุภาพ นะ สิ และ เถอะ ใช้ลดน้ำหนักหรือชักชวน ส่วน ล่ะ ไหม และ มั้ย ใช้ถาม คำลงท้ายที่ตามด้วยวรรคคือสัญญาณจุดตัดที่แรงที่สุดที่สตรีมภาษาไทยมี

  • คำลงท้ายที่ตามด้วยวรรค ได้แก่ ค่ะ ครับ คะ นะคะ นะครับ สิ เถอะ ล่ะ ไหม มั้ย หรือเปล่า ในคำตอบแบบสุภาพ คำเหล่านี้ปิดแทบทุกประโยค
  • การขึ้นบรรทัดใหม่ โมเดลภาษาเขียนให้ได้เมื่อสั่ง และซ็อกเก็ตสังเคราะห์เสียงทันทีโดยฝั่งไคลเอนต์ไม่ต้องมีตรรกะใด ๆ
  • วรรคหน้าคำที่มักขึ้นต้นประโยค เช่น แต่ แล้ว ส่วน ถ้า เพราะ ดังนั้น อย่างน้อยก็เป็นจุดแบ่งวลี และเป็นจังหวะหยุดที่ปลอดภัยในคำตอบยาว
  • เครื่องหมายคำพูดปิดหรือวงเล็บปิดที่ตามด้วยวรรค

คำลงท้ายบอกระดับภาษาของคำตอบ และบทความเรื่องความสุภาพอธิบายว่าทำไมผู้ช่วยที่ใช้ภาษาทางการจึงจบแทบทุกประโยคด้วยคำลงท้าย นิสัยนั้นเองที่ทำให้กฎคำลงท้ายเชื่อถือได้ ผู้ช่วยที่ถูกสั่งให้เขียนภาษาไทยแบบสุภาพจะสร้างจุดตัดของตัวเองขึ้นมา

ตัดตรงไหนแล้วฟังผิด#

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

  • หน้าคำลงท้าย การสังเคราะห์ที่ตัดก่อน ค่ะ จะทิ้งคำลงท้ายไว้เป็นช่วงของตัวเอง ถูกพูดโดด ๆ หลังช่องว่าง
  • กลางตัวเลข จำนวนเงิน หรือเวลา ๒,๕๐๐ บาท และ 14:30 น. คือหน่วยเสียงเดียว
  • ระหว่างคำนำหน้ากับชื่อ เช่น คุณ สมชาย หรือระหว่างชื่อกับคำลงท้ายที่ตามมา
  • หลังคำสันธาน ช่วงที่จบด้วย แต่ จะค้างอยู่กลางอากาศจนกว่าช่วงถัดไปจะมาถึง
  • ระหว่างกริยากับกรรมที่คร่อมวรรคแบ่งวลี ซึ่งผู้อ่านจะอ่านรวดเดียว

คำตอบสั้นคือหนึ่งช่วง การแบ่งคำตอบสิบสองคำเป็นสามช่วงไม่เพิ่มค่าเครดิตและไม่ลดความหน่วง เพราะช่วงแรกทำให้เสียงเริ่มพูดไปแล้ว

ให้โมเดลเขียนจุดตัดเอง#

ตัวตรวจจุดตัดที่ถูกที่สุดคือโมเดลภาษาเอง สั่งให้จบทุกประโยคด้วยการขึ้นบรรทัดใหม่ และให้แต่ละบรรทัดมีหนึ่งถึงสองวลี ซ็อกเก็ตสังเคราะห์เสียงเมื่อเจอบรรทัดใหม่ แต่ละช่วงคือหนึ่งประโยค และไคลเอนต์ไม่ต้องมีตรรกะเฉพาะภาษาไทยเลย

ไคลเอนต์ยังต้องส่งเฟรม flush เมื่อจบเทิร์น เพราะประโยคสุดท้ายอาจจบโดยไม่มีบรรทัดใหม่เมื่อโมเดลหยุดเขียน การ flush บัฟเฟอร์ว่างไม่มีผลข้างเคียง และอีเวนต์ flushed ยืนยันว่าบัฟเฟอร์ถูกระบายแล้ว

โมเดลที่ไม่ทำตามคำสั่งในคำตอบยาวก็ยังชนเกณฑ์ความยาวอยู่ดี และกฎคำลงท้ายด้านบนคือแผนสำรองสำหรับไคลเอนต์ที่อยากสังเคราะห์เร็วกว่านั้น ให้ตรวจคำลงท้ายแล้วตรวจวรรคที่ตามมา อย่าตรวจคำลงท้ายเพียงลำพัง ค่ะ กลางประโยคที่ยกมาคือคำลงท้ายในคำพูดที่อ้างถึง และวรรคต่างหากที่บอกว่าประโยคปิดแล้ว

การขัดจังหวะมีต้นทุนเท่าไร#

ผู้พูดพูดแทรกคำตอบ ไคลเอนต์ส่ง cancel ช่วงที่กำลังพูดหยุดลง และค่าใช้จ่ายของช่วงนั้นคงอยู่ เพราะข้อความนั้นถูกสังเคราะห์ไปแล้วก่อนคำสั่งขัดจังหวะมาถึง ข้อความในบัฟเฟอร์ที่ยังไม่เริ่มไม่เคยถูกคิดค่าใช้จ่าย และถูกทิ้งไป การเชื่อมต่อยังเปิดอยู่ และเฟรม text ถัดไปเริ่มช่วงใหม่ คู่มือ liveอธิบายลำดับการแลกเปลี่ยนนี้

การส่งหนึ่งประโยคต่อหนึ่งช่วงจำกัดต้นทุนของการขัดจังหวะไว้ที่ประโยคที่กำลังพูดอยู่ เครดิตคิดตามตัวอักษรไม่ว่าจะแบ่งกี่ช่วง และขั้นต่ำ 0.1 เครดิตคิดครั้งเดียวต่อการเชื่อมต่อ แต่ละช่วงนับเป็นหนึ่งคำขอต่อขีดจำกัดอัตราคำขอของแพลน และไคลเอนต์ที่ flush หลังทุกคำจะใช้โควตานั้นหมดไปโดยผู้ฟังไม่ได้ยินอะไรดีขึ้น

หนึ่งเทิร์น ทีละเฟรม#

ร่องรอยด้านล่างคือหนึ่งเทิร์นของผู้ช่วย สองประโยคแรกจบด้วยบรรทัดใหม่ที่โมเดลเขียน และซ็อกเก็ตสังเคราะห์แต่ละประโยคทันทีที่มาถึง ประโยคที่สามมาถึงโดยไม่มีบรรทัดใหม่ และ flush ของไคลเอนต์เมื่อจบเทิร์นเป็นตัวปิด

หนึ่งเทิร์นบนซ็อกเก็ต live
client  text     ได้เลยค่ะ\n
server  charged  leg 1
server  audio    ...
client  text     ร้านเปิดเก้าโมงเช้า
client  text     ถึงสองทุ่มค่ะ\n
server  charged  leg 2
server  audio    ...
client  text     วันอาทิตย์ปิดนะคะ
client  flush
server  charged  leg 3
server  audio    ...
server  flushed

อีเวนต์ charged แต่ละครั้งคือใบเสร็จของหนึ่งช่วง ผู้ฟังได้ยิน ได้เลยค่ะ ระหว่างที่โมเดลยังเขียนเวลาเปิดร้านอยู่ ซึ่งคือเหตุผลทั้งหมดของการสตรีมคำตอบ

ขั้นต่อไป#