Wednesday 5 July 2017

Echoprint โค๊ดเจน ไบนารี ตัวเลือก


สัปดาห์นี้ The Echo Nest เปิดตัว Echoprint 8211 ระบบลายนิ้วมือและการระบุลายเซ็นของเพลงโอเพ่นซอร์ส ระบบลายนิ้วมือเช่น Echoprint จะจดจำเสียงเพลงขึ้นอยู่กับว่าเสียงเพลงดังเช่นอะไร ไม่สำคัญว่าอัตราบิตอัตราตัวแปลงสัญญาณหรืออัตราการบีบอัดถูกนำมาใช้ (ขึ้นอยู่กับจุดใดจุดหนึ่ง) เพื่อสร้างไฟล์เพลงหรือไม่ก็เป็นเรื่องสำคัญที่มีการเชื่อมต่อเมตาดาต้าแบบแทบจะไม่ได้รับการเชื่อมต่อกับไฟล์เพลงถ้าเพลงดังเช่นเดียวกันเพลงริงโทน จะยอมรับว่า มีทั้งกลุ่มแอปพลิเคชันที่น่าสนใจจริงๆซึ่งสามารถสร้างขึ้นโดยใช้ fingerprinter เพลง ในบรรดาแอป iPhone ที่ฉันชื่นชอบคือ Shazam และ Soundhound 8211 ซึ่งเป็นแอปพลิเคชันการรู้จำเสียงแบบไร้สายที่ยอดเยี่ยมซึ่งช่วยให้คุณสามารถถือโทรศัพท์ได้ถึงวิทยุและจะบอกคุณในเวลาเพียงไม่กี่วินาทีว่าเพลงกำลังเล่นอยู่ ไม่แปลกใจเลยว่าแอปเหล่านี้เป็นผู้ขายชั้นนำใน App Store ของ iTunes พวกเขาเป็นสิ่งที่ใกล้เคียงที่สุดกับมายากล I8217ve ที่เห็นใน iPhone ของฉัน นอกเหนือจากแอ็พพลิเคชั่นสุดเซ็กซี่เช่น Shazam แล้วระบบระบุเพลงยังมีการใช้งานในรูปแบบต่างๆเช่นการบังคับใช้ลิขสิทธิ์ (การช่วยให้ไซต์ต่างๆอย่าง Youtube สามารถละเมิดลิขสิทธิ์ได้) การล้างข้อมูลเมตา (การติดตั้งศิลปินชื่ออัลบั้มและชื่อแทร็กที่เหมาะสม) ทุกแทร็กในคอลเล็กชันเพลง) และจับคู่แอพพลิเคชันสแกนอัจฉริยะเช่น Apple8217s เร็ว ๆ นี้จะได้รับการเผยแพร่บริการเพลง iCloud ที่ใช้การระบุเพลงเพื่อหลีกเลี่ยงการอัปโหลดเพลงที่ยาวและไม่จำเป็น การใช้ระบบระบุเพลงเป็นที่นิยมอย่างหนึ่งคือการยกเลิกการเก็บเพลง โปรแกรมต่างๆเช่น tuneup จะช่วยคุณค้นหาและกำจัดแทร็กที่ซ้ำกันในคอลเล็กชันเพลงของคุณ สัปดาห์นี้ฉันต้องการเล่นรอบกับระบบ Echoprint ใหม่ดังนั้นฉันจึงตัดสินใจ I8217d เขียนโปรแกรมที่ค้นหาและรายงานแทร็กที่ซ้ำกันในคอลเล็กชันเพลงของฉัน หมายเหตุ: หากคุณต้องการยกเลิกการจัดเก็บเพลงซ้ำ แต่คุณไม่ใช่โปรแกรมเมอร์โพสต์นี้ไม่เหมาะสำหรับคุณให้ไปหา tuneup หรือโปรแกรมยกเลิกการทำสำเนาอื่น ๆ จุดประสงค์หลักของบทความนี้คือเพื่อแสดงให้เห็นว่า Echoprint ทำงานอย่างไรไม่ใช่เพื่อแทนที่ระบบเชิงพาณิชย์ Echoprint ทำงานอย่างไร Echoprint เหมือนกับบริการระบุเพลงหลายเพลงเป็นกระบวนการหลายขั้นตอน: การสร้างโค้ดการกลืนกินและการค้นหา ในขั้นตอนการสร้างโค้ดคุณลักษณะทางดนตรีจะถูกแยกออกจากเสียงและเข้ารหัสเป็นสตริงข้อความ ในขั้นตอนการส่งผ่านรหัสจะมีการสร้างรหัสสำหรับเพลงทั้งหมดในคอลเล็กชันและเพิ่มลงในฐานข้อมูลที่สามารถค้นหาได้ ในขั้นตอนการค้นหาสตริง codegen จะถูกสร้างขึ้นสำหรับบิตเสียงที่ไม่รู้จักและใช้เป็นแบบสอบถามที่คลุมเครือไปยังฐานข้อมูลของรหัสที่ป้อนก่อนหน้านี้ หากพบข้อมูลการแข่งขันที่ให้คะแนนสูงอย่างเหมาะสมระบบจะส่งคืนข้อมูลในแทร็กที่ตรงกัน ปีศาจอยู่ในรายละเอียด การสร้างการแสดงระดับเสียงในระยะสั้นที่เหมาะสำหรับการค้นหาที่ไม่เกี่ยวกับการเข้ารหัส, อัตราบิต, เสียงและการแปลงอื่น ๆ ถือเป็นความท้าทาย ในทำนองเดียวกันความท้าทายเป็นตัวแทนรหัสในลักษณะที่ช่วยให้การสอบถามข้อมูลความเร็วสูงและช่วยให้การจับคู่ที่ไม่สมบูรณ์ของรหัสที่มีเสียงดัง Echoprint ประกอบด้วยส่วนประกอบหลัก 2 ส่วนคือ echoprint-codegen และ echoprint-server Code Generation echoprint-codegen มีหน้าที่รับผิดชอบในการรับเสียงและเปลี่ยนเป็นโค้ด echoprint คุณสามารถคว้าแหล่งข้อมูลจาก github และสร้างไบนารี่สำหรับแพลตฟอร์มท้องถิ่นของคุณ ไบนารีจะรับไฟล์เสียงเป็นอินพุตและให้เอาต์พุตบล็อกของ JSON ที่มีข้อมูลเมตาเพลง (ซึ่งพบในแท็ก ID3 ในเสียง) พร้อมกับสตริงโค้ด Here8217s ตัวอย่าง: ในตัวอย่างนี้ I8217m ได้พิมพ์ลายนิ้วมือเพียง 10 วินาทีแรกของเพลงเพื่อประหยัดเนื้อที่ สตริงโค้ดเป็นเพียงการเข้ารหัส base64 ของการบีบอัด zlib ของสตริงโค้ดเดิมซึ่งเป็นชุดเลขฐานสอง ASCII ที่มีการเข้ารหัสไว้ เวอร์ชันเต็มของรหัสนี้คือสิ่งที่จัดทำดัชนีโดยเซิร์ฟเวอร์การค้นหาสำหรับข้อความค้นหาลายนิ้วมือ codegen ค่อนข้างเร็ว จะสแกนเสียงที่เวลาจริง 250 เท่าต่อโปรเซสเซอร์หลังจากถอดรหัสและรีเซ็ตเป็น 11025 Hz ซึ่งหมายความว่าสามารถสแกนเพลงแบบเต็มได้ไม่เกิน 0.5 วินาทีในคอมพิวเตอร์โดยเฉลี่ยและสามารถสแกนเสียงที่เหมาะสำหรับการค้นหา (30 วินาที) ในเวลาน้อยกว่า 0.04 วินาที การถอดรหัสจาก MP3 จะเป็นคอขวดสำหรับการใช้งานส่วนใหญ่ ตัวถอดรหัสเช่น mpg123 หรือ ffmpeg สามารถถอดรหัสเสียง MP3 30s ไปเป็น 11025 PCM ในเวลาต่ำกว่า 0.10 วินาที เซิร์ฟเวอร์ Echoprint เซิร์ฟเวอร์ Echoprint มีหน้าที่ในการรักษาดัชนีรอยนิ้วมือของแทร็กนับล้าน ๆ ๆ ๆ ๆ เซิร์ฟเวอร์การค้นหาใช้ Apache Solr ที่เป็นที่นิยมเป็นเครื่องมือค้นหา เมื่อแบบสอบถามมาถึงรหัสที่มีการทับซ้อนกันสูงกับโค้ดแบบสอบถามจะถูกดึงข้อมูลโดยใช้ Solr เซิร์ฟเวอร์การค้นหาจะกรองผ่านผู้สมัครเหล่านี้และให้คะแนนตามปัจจัยหลายอย่างเช่นจำนวนการจับคู่รหัสคำสั่งลำดับและเวลาของรหัสเป็นต้น หากรหัสจับคู่ที่ดีที่สุดมีคะแนนสูงพอจะถือว่าเป็น Hit และรหัสประจำตัวและข้อมูลเมตาที่เกี่ยวข้องจะถูกส่งคืน เมื่อต้องการเรียกใช้เซิร์ฟเวอร์คุณจะต้องป้อนข้อมูลและจัดทำดัชนีรหัสแบบเต็มความยาวสำหรับแต่ละแทร็กเสียงที่สนใจลงในดัชนีเซิร์ฟเวอร์ ในการค้นหาคุณใช้ echoprint-codegen เพื่อสร้างโค้ดสำหรับเซ็ตย่อยของไฟล์ (โดยปกติจะใช้เวลา 30 วินาที) และออกให้เป็นแบบสอบถามไปยังเซิร์ฟเวอร์ รังนกโฮสต์เซิร์ฟเวอร์การค้นหาดังนั้นสำหรับกรณีการใช้งานจำนวนมากที่คุณชนะ8217tต้องใช้เซิร์ฟเวอร์การค้นหาของคุณเอง แทน. คุณสามารถส่งคำร้องไปยัง Echo Nest โดยใช้การเรียกร้อง songidentify (เราคาดว่าหลายคนอาจใช้เซิร์ฟเวอร์ echoprint สาธารณะด้วย) การสร้างเครื่องสำรองข้อมูลด้วยการแนะนำอย่างรวดเร็วว่า Echoprint ใช้งานได้อย่างไร let8217s มองว่าเราสามารถสร้างเครื่องสำรองข้อมูลได้อย่างไร ตรรกะหลักเป็นเรื่องง่ายมากเราสร้างฐานข้อมูลลายนิ้วมือเปล่า สำหรับแต่ละเพลงในคอลเล็กชันเพลงเราจะสร้างโค้ด Echoprint และค้นหาเซิร์ฟเวอร์สำหรับการจับคู่ ถ้าเราพบไฟล์หนึ่งแล้ว mp3 จะซ้ำกันและเรารายงาน มิฉะนั้นจะเป็นแทร็กใหม่ดังนั้นเราจะนำโค้ดสำหรับแทร็กใหม่เข้าสู่เซิร์ฟเวอร์ echoprint ล้าง. ทำซ้ำ I8217ve เขียน python program dedup. py เพื่อทำเพียงแค่นี้ เป็นแบบระมัดระวังฉัน don8217t มีจริงลบรายการที่ซ้ำกัน แต่ฉันมีเพียงสร้างรายงานซ้ำเพื่อฉันสามารถเลือกที่ฉันต้องการเก็บ โปรแกรมยังติดตามสถานะของคุณเพื่อให้คุณสามารถเรียกใช้งานได้อีกครั้งเมื่อใดก็ตามที่คุณเพิ่มเพลงใหม่ลงในคอลเล็กชันของคุณ Here8217s ตัวอย่างของการรันโปรแกรม: Dedup. py พิมพ์แต่ละไฟล์ mp3 ขณะประมวลผลและพบรายงานที่ซ้ำกัน นอกจากนี้ยังเก็บรวบรวมรายงานที่ซ้ำกันในไฟล์ในรูปแบบ pblml เช่น: อีกครั้ง dedup. py doesn8217t ลบรายการที่ซ้ำกันจริง ๆ แล้วมันก็จะทำให้คุณได้รับรายงานซ้ำซ้อนของรายการที่ซ้ำกันในคอลเล็กชันของคุณ หากคุณต้องการทดลองใช้ dedup. py ให้ทำตามขั้นตอนต่อไปนี้: ดาวน์โหลดสร้างและติดตั้ง echoprint-codegen ดาวน์โหลดสร้างติดตั้งและเรียกใช้เซิร์ฟเวอร์ echoprint ดูข้อมูล dedup. py แก้ไขบรรทัดที่ 10 ใน dedup. py เพื่อตั้งค่า sys. path เพื่อชี้ไปที่ echoprint-server API directory แก้ไขบรรทัดที่ 13 ใน dedup. py เพื่อตั้ง codegenpath ให้ชี้ไปที่ echoprint-codegen executable ซึ่งจะพบ dups และ write ทั้งหมด ไฟล์ dedup. dat ใช้เวลาประมาณ 1 วินาทีต่อเพลง เมื่อต้องการเริ่มต้นใหม่ (ขั้นตอนนี้จะลบฐานข้อมูลลายนิ้วมือของคุณ) ให้รัน: โปรดทราบว่าคุณสามารถเรียกใช้กระบวนการซิงเกิลได้โดยไม่ต้องใช้เซิร์ฟเวอร์ echoprint ของตัวเอง (ช่วยประหยัดปัญหาในการติดตั้งตู้ของ Apache-Solr ตู้โตเกียวและตู้โตเกียว) ข้อเสียคือคุณ wins8217t มีเซิร์ฟเวอร์แบบถาวรซึ่งหมายความว่า you8217ll ไม่สามารถเพิ่มคอลเล็กชัน 8211 you8217 ได้ตามต้องการในทุกๆครั้ง หากต้องการใช้โหมดโลคัลให้เพิ่ม local-True ลงในการเรียก fp. py ดัชนีจะถูกเก็บไว้ในหน่วยความจำไม่มี solr หรือเผด็จการโตเกียวเป็นสิ่งจำเป็น การห่อหุ้ม dedup. py เป็นเพียงตัวอย่างเล็กน้อยของแอ็พพลิเคชันที่นักพัฒนาซอฟต์แวร์สามารถสร้างขึ้นโดยใช้ Echoprint ฉันคาดว่าจะเห็นมากขึ้นในอีกไม่กี่เดือนข้างหน้า ก่อน Echoprint การระบุตัวตนของเพลงอยู่ห่างไกลจากผู้พัฒนาแอปพลิเคชันเพลงทั่วไปแล้วมันก็แพงเกินไป ขณะนี้มี Echoprint ทุกคนสามารถใช้เทคโนโลยีการระบุเพลงลงในแอปได้ ผลลัพธ์ที่ได้จะลดน้อยลงสำหรับนักพัฒนาซอฟต์แวร์และแอปพลิเคชันเพลงที่ดียิ่งขึ้นสำหรับทุกคน แบ่งปันสิ่งนี้: Irsquove กำลังทำงานร่วมกับรหัสลายนิ้วมือแบบโอเพ่นซอร์ส EchoPrint เป็นส่วนหนึ่งขององค์ประกอบการวิเคราะห์เสียงของโครงการต้นแบบของฉัน การพิมพ์ลายนิ้วมือเป็นส่วนหนึ่งของสิ่งที่แอพพลิเคชันการจดจำเพลงทั้งหมดทำบนโทรศัพท์ - การสร้างรหัสลายนิ้วมือซึ่งแสดงถึงส่วนของรูปคลื่นของเพลงซึ่งสามารถเปรียบเทียบกับฐานข้อมูลลายนิ้วมือเพื่อระบุเพลงได้ EchoPrint เป็นชื่อ implies สร้างรหัสลายนิ้วมือที่สามารถมองขึ้นในฐานข้อมูล EchoNest ซึ่งฉันคิดว่าจะเป็นแหล่งข้อมูลการวิเคราะห์เพลงที่ดีสำหรับโครงการของฉัน เมื่อฉันได้รับมันทั้งหมดตะขอ, Irsquoll โพสต์คำอธิบายขององค์ประกอบทั้งหมดเหล่านี้จะใช้ในโครงการของฉัน ในพื้นที่เก็บข้อมูล GitHub สำหรับโค้ด echoprint มีตัวอย่างแอป iOS ที่แสดงวิธีการใช้ fingerprinter แต่ก็ค่อนข้างซับซ้อน รหัส fingerprinter ต้องการให้คุณส่งบัฟเฟอร์ของค่าตัวอย่าง PCM ที่ไม่มีการบีบอัดมาเป็นเวลาประมาณ 30 วินาทีของเพลงที่คุณพยายามระบุ โค้ดตัวอย่างใช้ไลบรารีภายนอกเพื่อแปลงไฟล์เสียงที่บีบอัดไปยัง PCM เขียน PCM ไปยังไฟล์ใหม่อ่านไฟล์ใหม่ ๆ กลับเข้าสู่แรมให้ลดข้อมูลลงในแรมแล้วลูปจะผ่านช่วงเวลา 30 วินาทีเพื่อเก็บบัฟเฟอร์ สำหรับลายนิ้วมือ วิธีที่ง่ายและมีประสิทธิภาพมากขึ้นคือการใช้บริการไฟล์เสียงเสียงหลักที่มีอยู่ในทั้ง OS X และ iOS ขั้นตอนที่ต้องการคือการสร้าง ExtAudioFileRef สำหรับไฟล์เสียงบีบอัดและแนบคำอธิบายรูปแบบ PCM เป็นแอตทริบิวต์ Format Client ExtAudioFileRefrsquos จากนั้นอ่าน 30 วินาทีแรกของไฟล์ลงในบัฟเฟอร์ Client Format จะทำให้ผลลัพธ์ของการอ่านอยู่ในรูปแบบ PCM ที่ระบุ บัฟเฟอร์นี้สามารถส่งผ่านไปยัง fingerprinter ได้โดยตรง โค้ดด้านล่างแสดงวิธีการทำเช่นนี้ SoundAndMusicForInteractiveGames, Core Audio, โกโก้, Objective-C, C, การเขียนโปรแกรมเสียง, EchoPest, EchoPrint, เกี่ยวกับ Bleeps และ Pops Im Jim McGowan ผมสอน Sound Design ที่ Hong Kong Academy of Performing Arts และเพิ่งจบปริญญาโทด้านเสียงและดนตรีสำหรับ Interactive Games ที่ Leeds Metropolitan University บล็อกนี้ครอบคลุมเนื้อหาที่เกี่ยวข้องกับเรื่องนี้และวิชาที่คล้ายกัน Code for Echoprint Echoprint เป็นลายนิ้วมือเพลงที่เปิดกว้างและกรอบการแก้ไขที่ขับเคลื่อนโดย The Echo Nest เครื่องกำเนิดไฟฟ้ารหัส (ห้องสมุดเพื่อแปลงตัวอย่าง PCM จากไมโครโฟนหรือไฟล์ลงในรหัส Echoprint) เป็นโอเพนซอร์ส (MIT ที่ได้รับอนุญาต) และฟรีสำหรับการใช้งานใด ๆ คอมโพเนนต์เซิร์ฟเวอร์ที่เก็บและแก้ไขข้อความค้นหาคือโอเพนซอร์ส (Apache 2 licenses) และฟรีสำหรับการใช้งานใด ๆ ข้อมูลสำหรับการแก้ไขให้เป็นล้านเพลงเป็นบริการฟรีสำหรับการใช้งานใด ๆ หากมีการเปลี่ยนแปลงหรือเพิ่มเติมใด ๆ ที่รวมเข้ากับชุมชน มีสองโหมดการทำงานของ codegen ของ Echoprint: ไลบรารี codegen (libcodegen) หมายถึงการเชื่อมโยงเป็นรหัสที่ส่งผ่านข้อมูลบัฟเฟอร์ของข้อมูล PCM และจะส่งออกสตริงโค้ด ไบต์ codegen ทำงานแบบสแตนด์อโลนยอมรับชื่อไฟล์เป็นอินพุทและทำงานในโหมดผู้ทำงานแบบมัลติเธรด ข้อกำหนดเพิ่มเติมสำหรับ codegen binary TagLib ffmpeg - นี่เรียกว่าผ่านทาง shell และไม่มีการเชื่อมโยงกับ codegen ใน Ubuntu หรือ Debian คุณสามารถติดตั้ง dependencies เหล่านี้ได้ด้วย: ใน OS-X กับ homebrew คุณสามารถใช้: ดูเอกสารภายใต้โฟลเดอร์ windows สำหรับ รายละเอียดเพิ่มเติม ไบนารีที่สร้างขึ้นใน Windows จะมีชื่อว่า codegen โดยค่าเริ่มต้นเช่นเดียวกับใน Linux หรือ Mac OS-X ชื่อ echoprint-codegen หมายเหตุเกี่ยวกับ libcodegen: การสร้างโค้ดจะใช้บัฟเฟอร์ของข้อมูล PCM ข้อมูลแบบลอยตัวที่สุ่มตัวอย่างที่ 11025 Hz และ mono สตริงโค้ดเป็นเพียงการเข้ารหัส base64 ของการบีบอัด zlib ของสตริงโค้ดเดิมซึ่งเป็นชุดเลขฐานสอง ASCII ที่มีการเข้ารหัสไว้ ดู APIfp. py ใน echoprint-server เพื่อรับความช่วยเหลือในการถอดรหัส คุณต้องค้นหาเสียงเป็นเวลา 20 วินาทีเพื่อให้ได้ผลลัพธ์ หมายเหตุเกี่ยวกับไบนารี codegen Makefile สร้างเครื่องกำเนิดไฟฟ้าโค้ดตัวอย่างที่ใช้ libcodegen เรียกว่า codegen เครื่องกำเนิดไฟฟ้ารหัสนี้มีคุณสมบัติมากขึ้น - จะออกข้อมูลแท็ก ID3 และใช้ ffmpeg เพื่อถอดรหัสไฟล์ประเภทใด ๆ หากคุณไม่จำเป็นต้องคอมไพล์ libcodegen ลงในแอปพลิเคชันของคุณคุณสามารถวางใจได้ โปรดทราบว่าคุณจำเป็นต้องมี ffmpeg ที่ติดตั้งและเข้าถึงได้บนเส้นทางของคุณสำหรับการทำงานนี้ จะใช้เวลา 30 วินาทีของเสียงจาก 10 วินาทีในไฟล์และเอาต์พุต JSON เหมาะสำหรับการสืบค้น: คุณสามารถ POST JSON นี้โดยตรงไปยัง Echo Nests songidentify (ผู้ที่มีเซิร์ฟเวอร์ Echoprint booted) เช่น: หรือคุณสามารถโฮสต์เซิร์ฟเวอร์ Echoprint ของคุณเอง และกินหรือสอบถามไปที่ Codegen ยังทำงานในโหมดมัลติเธรดสำหรับการแก้ไขจำนวนมาก: จะคำนวณรหัสสำหรับไฟล์ทุกไฟล์ในรายการ filelist เป็นเวลา 30 วินาทีเริ่มต้นที่ 10 วินาที (มันพยายามที่จะสมาร์ทเกี่ยวกับจำนวนของหัวข้อที่จะใช้.) จะออกรายการ JSON โปรดทราบว่า songidentify สามารถยอมรับรายการใน JSON ซึ่งจะเร็วกว่าการส่งแต่ละรหัสทีละครั้ง พารามิเตอร์แท็กถูกเพิ่มลงในพจนานุกรมรหัสแต่ละฉบับเพื่อให้ตรงกับเนื้อหาที่แก้ไข Codegen จะสแกนเสียงตามเวลาจริง 250 เท่าต่อโปรเซสเซอร์หลังจากถอดรหัสและรีเซ็ตเป็น 11025 Hz ซึ่งหมายความว่าสามารถสแกนเพลงแบบเต็มได้ไม่เกิน 0.5 วินาทีในคอมพิวเตอร์โดยเฉลี่ยและสามารถสแกนเสียงที่เหมาะสำหรับการค้นหา (30 วินาที) ในเวลาน้อยกว่า 0.04 วินาที การถอดรหัสจาก MP3 จะเป็นคอขวดสำหรับการใช้งานส่วนใหญ่ ตัวถอดรหัสเช่น mpg123 หรือ ffmpeg สามารถถอดรหัสเสียง MP3 30s ไปเป็น 11025 PCM ในเวลาต่ำกว่า 0.10 วินาที ดูข้อมูล echoprint. me เกี่ยวกับความถูกต้องของระบบ echoprint ถาม: ฉันไม่สามารถถอดรหัสตัวอย่างใด ๆ ได้ด้วย: ffmpeg เมื่อใช้ codegen A: เมื่อใช้เครื่องสร้างโค้ดตัวอย่าง (echoprint-codegen) ให้แน่ใจว่า ffmpeg สามารถเข้าถึงเส้นทางของคุณได้ ลองใช้ ffmpeg filename. mp3 ในไฟล์ที่คุณกำลังทดสอบเครื่องกำเนิดไฟฟ้าโค้ดด้วย ถ้ามันไม่ได้ทำงาน codegen เคยชินทำงาน

No comments:

Post a Comment