پلتفرم کلودفلر استریم (Cloudflare Stream) یک پلتفرم پخش قدرتمند است که برای بسیاری از مشتریان ما به سادگی و بدون مشکل کار میکند. اما اگر بخواهید انیمیشنهای پویا را روی یک ویدیوی زنده رندر کنید یا نسخه جایگزینی از یک ویدیوی میزبانیشده با زیرنویسهای چسبیده ایجاد کنید چه؟ در این صورت شما نیاز به اجرای یک پایپلاین ویدیوی سفارشی دارید.
امروز، ما در حال انتشار یک محیط توسعه جدید به نام استریملاین (Streamline) هستیم که نشان میدهد چگونه میتوانید سیستمی برای ارائه این تجربههای ویدیویی سفارشی روی پلتفرم توسعهدهندگان کلودفلر (Cloudflare’s Developer Platform) بسازید. ما به شما نشان خواهیم داد که چگونه استریملاین از ورکرهای کلودفلر (Workers)، کانتینرها (Containers) و چندین پروتکل رسانهای برای تغییر ویدیو استفاده میکند و بلافاصله آن خروجی را به عنوان پخش زنده یا ویدیوی میزبانیشده جدید منتشر میکند. همچنین این فرصت را خواهید داشت تا آن را برای پروژههای خود امتحان کنید.
یک پایپلاین پردازشی به یک محیط پایدار و طولانیمدت نیاز دارد که بتواند کد کامپایلشده و تخصصی را با ظرفیت حافظه و پردازنده قابل پیشبینی اجرا کند. استریمهای ویدیویی میتوان رسماً برای دقایق یا ساعتها اجرا شوند، بنابراین فرآیند رسانه به چرخهی حیات مستقل از درخواستی که آن را آغاز کرده است، نیاز دارد. یک برنامه باید قادر باشد یک پایپلاین را راهاندازی کند، ورودی خود را ارسال نماید، آن را بازرسی کند و بدون نیاز به باز نگه داشتن یک درخواست واحد برای کل مدت زمان، آن را متوقف سازد.
کلودفلر اصول اولیهای را که ما نیاز داریم فراهم میکند. کانتینرها (Containers) محیطهای اجرایی طولانیمدتی هستند که برای پردازش رسانه مناسباند. اشیاء بادوام (Durable Objects) در ارکستراسیون کمک میکنند. در نهایت، ورکرها (Workers) برای سیگنالدهی کنترل و نظارت بسیار مناسب هستند.
برای استریملاین، ما یک موتور رسانهای ساختیم که در یک کانتینر (Container) اجرا میشود تا پردازش رسانه را به صورت بلادرنگ مدیریت کند. این کانتینر توسط یک ورکر (Worker) کنترل میشود که کنترل، پیشنمایش و تست را در اختیار یک ایجنت یا کاربر قرار میدهد. پردازش حتی اگر ورکر قطع شود نیز ادامه خواهد یافت. ما استریملاین را با قطعات ماژولار معماری کردهایم تا موتور رسانه در آینده بتواند با محصولات انکدینگ اختصاصی جایگزین شود.
معماری (Architecture)
یک استقرار استریملاین شامل دو جزء است: موتور رسانه (Media Engine) که ورودی/خروجی رسانه و پردازش را مدیریت میکند، و یک برنامه (Application) کنترلکننده که جلسات رسانهای را ایجاد، پیکربندی، مشاهده و متوقف میکند.
موتور رسانه (Media Engine)
موتور رسانه دارای دو جزء است:
- کنترلر (Controller): این یک ابزار کنترلی است که به زبان Go نوشته شده و یک سرور HTTP را پیادهسازی میکند، درخواستهای ورودی را دریافت کرده و آنها را به عملیاتی تبدیل میکند که میتوانند توسط موتور رسانه اجرا شوند.
- پردازنده (Processor): پردازندهای که پردازش واقعی رسانه را انجام میدهد. پیادهسازی فعلی از FFmpeg استفاده میکند، اما این یک جزئیات پیادهسازی داخلی است تا بخشی از API رو به کاربر.
موتور رسانه در یک کانتینر میزبانی میشود و تمام ورودی/خروجیهای رسانه و همچنین پردازش را مدیریت میکند. این موتور میتواند پخش RTMPS را از طریق شبکه از یک ورودی استریم لایو (Stream Live) بکشد و خروجی RTMPS را به یک ورودی استریم لایو دیگر منتشر کند. این ابزار میتواند یک مانیفست HLS کلودفلر استریم و بخشهای آن را برای استفاده از ویدیوهای میزبانیشده به عنوان ورودی بکشد. این سیستم میتواند ورودی ویدیو را از یک منبع ارائهشده توسط برنامه کنترلکننده، مانند وبکم، بپذیرد. همچنین میتواند ویدیوی پیشنمایش را از طریق یک وبسوکت خروجی به یک رله اشیاء بادوام (Durable Object relay) منتشر کند. برنامهای که به پیشنمایش نیاز دارد میتواند از طریق وبسوکت خود به آن رله متصل شود.
برنامه (Application)
این برنامه با استفاده از ورکرها (Workers) ساخته شده است و میتواند یک برنامه مرورگر فولاستک، یک ایجنت یا یک سیستم تعبیهشده باشد. این شامل موارد زیر است:
- رابط کاربری (UI) شامل منطق کلاینت، هویت و سیاست دسترسی. این مقاله از یک برنامه مرورگر به عنوان مثال ملموس خود استفاده میکند، بنابراین شامل یک رابط مرورگر نیز میشود.
- ارکستراتور (Orchestrator) جلسه، چرخه حیات کانتینر و رله پیشنمایش را هماهنگ میکند. ارکستراتور توسط یک شیء بادوام (Durable Object) پیادهسازی میشود.
امکان اجرای سیستم به صورت محلی در طول توسعه وجود دارد، در این صورت کانتینر فقط یک نمونه محلی داکر (Docker) است و شیء بادوام استفاده نمیشود: یک کاربر واحد وجود دارد، برنامه کنترلکننده برای دسترسی محلی نیازی به احراز هویت ندارد و پیشنمایش ویدیو میتواند مستقیماً به یک وبسوکت روی لوکالهاست متصل شود.
هنگامی که این قطعات روی کلودفلر مستقر میشوند، یک کاربر یا ایجنت مجاز میتواند برای شروع یک جلسه جدید به ورکر مراجعه کند. این کار در صورت نیاز یک کانتینر جدید استریملاین را راهاندازی میکند، چرخه حیات آن را به طور خودکار مدیریت میکند، یک API برای انجام تعدادی از عملیات دستکاری ویدیو آشکار میسازد و ورودیها را از کلودفلر استریم و خروجیها را به آن هدایت میکند.
اکنون وقت یک بررسی عمیق فنی در مورد نحوه کارکرد سیستم است.
چرخه حیات کانتینر و مدیریت جلسه (Container lifecycle and session management)
برنامه ورکر کنترلکننده یک جلسه پردازش رسانه طولانیمدت را آغاز میکند. پس از شروع جلسه، برنامه میتواند با خیال راحت قطع و دوباره متصل شود، در حالی که کانتینر به پردازش خود ادامه میدهد تا زمانی که برنامه کنترلکننده آن را متوقف کند. ما همچنین یک مدت زمان حداکثر را برای اطمینان از این موضوع قرار دادهایم که یک جلسه همیشه در نهایت بسته شود و نتواند به طور نامحدود، حتی بدون کنترل خارجی، اجرا شود. در حالی که یک جلسه پردازش رسانه در حال اجرا است، نمونه کانتینر برای استفاده سایر برنامهها در دسترس نیست.
یک کانتینر کلودفلر به طور خودکار اگر هیچ درخواست ورودی را از زمان بازه زمانی تعریفشده دریافت نکرده باشد، به حالت خواب میرود. با این حال، در مورد ما، هنگامی که پایپلاین در حال اجرا است، باید حتی اگر برنامه کنترلکننده قطع شود و هیچ درخواستی دریافت نکند، به کار خود ادامه دهد. ما میتوانیم این رفتار را با بازنویسی کالبک onActivityExpired() روی کانتینر پیادهسازی کنیم. اگر زمان انقضا نرسیده باشد، فعالیت را تمدید میکنیم، در غیر این صورت کانتینر را نابود میکنیم.
رابط برنامهنویسی کاربردی (API)
سرور HTTP پیادهسازیشده توسط ابزار Go و شیء بادوام مرتبط با کانتینر با هم رابط سطح پایین سیستم را تعریف میکنند. با این حال، ما میخواستیم یک لایه انتزاعی روی این ارائه دهیم، به طوری که سیستم تا حد امکان نسبت به اینکه چه کسی یا چه چیزی جلسه را کنترل میکند و هرگونه جزئیات غیرضروری پیادهسازی بکاند بیتناسب باشد.
ما این را با صادرات دو پکیج از استریملاین پیادهسازی میکنیم:
@cloudflare/streamline/clientیک API مبتنی بر جلسه سطح بالا را تعریف میکند.@cloudflare/streamline/کلاس پایه شیء بادوام مرتبط با کانتینر را آشکار میسازد. این درخواستهای API را مسیریابی میکند، سرور رله پیشنمایش توصیفشده در زیر را پیادهسازی میکند و قلابهایی را برای امنیت و سیاست دسترسی فراهم میکند.
در یک استقرار از راه دور، انتظار میرود که ورکر کنترلکننده @streamline/cloudflare را ایمپورت کند و یک زیرکلاس مشخص از شیء بادوام آشکارشده توسط کانتینر را تعریف کند که میتواند برای منطق و فضای ذخیرهسازی خاص برنامه استفاده شود.
در حالت محلی، جایی که هیچ شیء بادوام وجود ندارد، فرانتاند یک لایه آداپتور نازک تعریف میکند که API مبتنی بر جلسه را حفظ میکند، اما مستقیماً به نمونه محلی داکر بدون کنترل دسترسی و غیره متصل میشود.
مثال زیر نشان میدهد که چگونه برنامه کنترلکننده میتواند از API برای دسترسی به استریملاین، آمادهسازی یک جلسه و شروع یک پایپلاین پردازش ویدیو استفاده کند.
مقدار config یک شیء JSON است که پایپلاین پردازشی را که باید اجرا شود تعریف میکند، که در بخشهای بعدی بیشتر توضیح داده شده است.
جدول زیر لیست کامل تمام فرازهای API را نشان میدهد.
| متد کلاینت | عملکرد |
|---|---|
createStreamline() | یک نمونه جدید از استریملاین ایجاد میکند. |
streamline.sessions.create() | یک جلسه پردازش جدید ایجاد میکند. |
streamline.sessions.resume(id) | به یک جلسه موجود مجدداً متصل میشود. |
session.start(config) | یک پایپلاین پردازش جدید را شروع میکند. |
session.ingest(chunk) | یک تکه از دادههای ویدیو را در حالت «وبکم» ارسال میکند. |
session.annotation(png) | پوشش حاشیهنویسی شفاف را بهروزرسانی میکند. |
session.metrics() | متریکهایی را درباره جلسه فعلی دریافت میکند. |
session.stop() | پردازش را در جلسه فعلی متوقف میکند. |
تعریف و اجرای یک پایپلاین پردازش ویدیو (Defining and running a video processing pipeline)
متد session.start() یک پایپلاین پردازشی را ساخته و اجرا میکند. این متد یک آرگومان منفرد میگیرد که یک شیء پیکربندی JSON است که پردازش مورد نظر را تعریف میکند:
- ورودیها (Inputs)
- عملیات (Operations)
- خروجی (Output)
مثال زیر پایپلاین را شروع میکند که یک پخش RTMP (پروتکل پیامرسانی بلادرنگ) را به عنوان ورودی میگیرد (برای مثال، فید ورودی استریم لایو که یک پخش زنده ورودی را دریافت میکند)، یک تصویر پوششی با شفافیت اعمال میکند و خروجی را به یک مقصد RTMP ارسال میکند (برای مثال، به یک ورودی استریم لایو دیگر برای ضبط یا پخش). این کار به برنامه ورکر اجازه میدهد تا یک نسخه اصلاحشده از یک پخش زنده را به صورت بلادرنگ ایجاد کند.
ورودی ویدیوی درخواستی از طریق HLS (Video-on-demand input via HLS)
استریملاین همچنین میتواند ورودی ویدیوی در حال پخش را از طریق HLS (پخش زنده HTTP) دریافت کند، برای مثال ویدیویی که روی کلودفلر استریم میزبانی میشود. مثال زیر نشان میدهد که چگونه یک برنامه ورکر میتواند پایپلاینی را اجرا کند که یک ویدیوی استریم را دریافت میکند، زیرنویسهای بسته تعبیهشده را میخواند و آنها را به عنوان متن روی ویدیو رندر میکند، و خروجی را از طریق RTMP ارسال میکند، برای مثال به یک ورودی استریم لایو برای پخش یا ضبط نسخه اصلاحشده.
ارسال ویدیو به استریملاین (Sending video to Streamline)
اغلب برای پیشنمایش سریع یک پایپلاین پردازشی با ارسال دادههای ویدیویی به طور مستقیم به استریملاین، برای مثال از یک وبکم، بسیار مفید است. یک ایجنت یا برنامه دستگاه تعبیهشده نیز ممکن است بخواهد از این قابلیت استفاده کند، برای مثال برای ارسال فیلم از دوربینهای کارخانه برای تحلیل هوش مصنوعی، یا ترکیب چندین فید دوربین در یک نمای مرکب.
مثال زیر پایپلاینی را ایجاد میکند که انتظار ورودی از برنامه ورکر را دارد و خروجی ویدیوی پیشنمایش را از طریق یک وبسوکت در دسترس قرار میدهد (در ادامه بیشتر درباره ویدیوی پیشنمایش وبسوکت صحبت خواهیم کرد). این کد دو فیلتر و یک «حاشیهنویسی» اعمال میکند که یک پوشش مشخصشده به صورت تصویر PNG است که میتواند در طول اجرای پردازش بهروزرسانی شود، برای مثال برای پیادهسازی یک گرافیک متحرک.
قطعه کد بالا فقط پایپلاین را شروع میکند. ورکر کنترلکننده هنوز هیچ رسانهای را به استریملاین ارسال نمیکند. ما در ادامه درباره تابع openViewer() بحث خواهیم کرد.
برنامه ورکر دادههای ویدیو را با استفاده از فراخوانی session.ingest() به استریملاین ارسال میکند. مثال زیر نشان میدهد که چگونه یک برنامه مرورگر وب ممکن است تکههایی را از وبکم دریافت کند و آنها را به استریملاین هدایت کند.
پوشش متحرک (Animated overlay)
پوشش حاشیهنویسی را میتوان با استفاده از فراخوانی session.annotation() بهروزرسانی کرد. مثال زیر نشان میدهد که چگونه برنامه ورکر میتواند از یک بوم (canvas) عکس فوری بگیرد و آن را به استریملاین ارسال کند. این کار را میتوان روی یک حلقه انیمیشن انجام داد، اگرچه نرخ بهروزرسانی ممکن است در عمل توسط اندازه تصاویر پوششی PNG، پهنای باند موجود و قدرت پردازش محدود شود.
دریافت ویدیوی پیشنمایش از استریملاین (Receiving preview video from Streamline)
استریملاین همچنین میتواند با مشخص کردن output: { mode: 'websocket' } خروجی ویدیوی پیشنمایش تولید کند.
استریملاین از وبسوکتها برای تحویل ویدیوی پیشنمایش با تأخیر کم به برنامه کنترلکننده استفاده میکند: کانتینر قطعات fMP4 را به شیء بادوام منتشر میکند، که آنها را به یک رله خروجی در دسترس روی وبسوکت در URL /relay/view، نسبی به مبدأ برنامه هدایت میکند. برنامه باید یک وبسوکت را به این URL متصل کند و سپس دادههای ویدیویی را که به محض در دسترس قرار گرفتن از استریملاین به آن فشار داده میشود، دریافت خواهد کرد. قطعه کد بالا نشان میدهد که چگونه یک برنامه مرورگر وب ممکن است فید ویدیوی پیشنمایش را نمایش دهد.
یک پلیر MediaSource در سطح تولید باید قطعات را زمانی که SourceBuffer.updating برابر با true است، در صف قرار دهد. در توسعه محلی، مرورگر یا سایر برنامههای کنترلکننده به سادگی یک اتصال وبسوکت را مستقیماً روی کانتینر محلی باز میکنند.
عملیات پشتیبانیشده فعلی (Currently supported operations)
در شیء پیکربندی ارسالشده به session.start() در مثالهای بالا، pipeline آرایهای از عملیات از مجموعه پشتیبانیشده توسط موتور رسانه زیرین است. ترتیب عملیات در حال حاضر توسط موتور ثابت است؛ ترتیبی که در آرایه مشخص شده است معنادار نیست. لیست عملیات پشتیبانیشده فعلی و ترتیبی که در آنها اعمال میشوند در زیر آمده است.
| نام عملیات | عملکرد |
|---|---|
filter | عملیات فیلترینگ مانند تار کردن، اشباع رنگ را اعمال میکند. |
امنیت (Security)
این کلودفلر است، بنابراین مهم است که امنیت بخشی از طراحی باشد تا یک اضافهکاری در انتها. ما باید اطمینان حاصل کنیم که فقط کاربران مجاز میتوانند یک جلسه جدید ایجاد کنند یا کنترل یک جلسه موجود را به دست گیرند و جلسات از یکدیگر ایزوله شوند. ما باید کلیدهای ورودی/خروجی استریم RTMPS را به عنوان رازهایی در نظر بگیریم که نباید به برنامه کنترلکننده درز کنند. ما باید اطمینان حاصل کنیم که استفاده از منابع محدود است.
استقرار مالک با استفاده از یکپارچهسازی دسترسی ورکرها خصوصی نگه داشته میشود. هویت مالک پیکربندیشده و سایر کاربران مجاز میتوانند پروفایلهای مشترک یکسانی را ویرایش کنند و در حالی که تکنمونه (singleton) بیکار است، یک جلسه را شروع کنند. ورکر جلسه دسترسی را قبل از پذیرش درخواستهای کنترل تأیید میکند و جلسه فعال را به اصل تأییدشده متصل میکند. تنها یک جلسه میتواند در یک زمان اجرا شود و یک اصل متفاوت نمیتواند جلسه فعال را متوقف یا جایگزین کند.
کلیدهای ورودی استریم لایو در رازهای ورکر یا به عنوان بازنویسیهای مشترک فقط نوشتنی در فضای ذخیرهسازی شیء بادوام ذخیره میشوند. آنها هرگز توسط تنظیمات API بازگردانده نمیشوند یا در فضای ذخیرهسازی مرورگر قرار نمیگیرند. برنامه کنترلکننده ورودی و خروجی RTMPS را با ارجاع به یک پروفایل نامگذاریشده مشخص میکند. ورکر پروفایل را قبل از تماس با کانتینر حل میکند.
استریم ویدیوی پیشنمایش دارای دو اعتبار با اهداف جداگانه است. یک توکن سرویس کلودفلر Access بار کاری کانتینر را در پایانه ناشر احراز هویت میکند. یک قابلیت تصادفی به ازای هر جلسه، انتشار را فقط برای رله فعال در حال حاضر مجاز میسازد. توکن سرویس توسط ورکر خروجی کانتینر تزریق میشود و هرگز وارد حافظه کانتینر نمیشود. استقرار اولیه از یک مسیر موقت خاص Access Bypass استفاده میکند در حالی که قابلیت به ازای هر جلسه اجباری باقی میماند؛ پس از استقرار و یک تست دود موفقیتآمیز، عرضه Bypass را با احراز هویت سرویس (Service Auth) جایگزین میکند.
استقرار مالک عمداً خصوصی و مسیریابیشده با تکنمونه است. این مدل امنیتی برای یک سرویس چندکاربره عمومی نیست.
زمین بازی و متنباز (Playground and open source)
ما میخواهیم شما استریملاین را امتحان کنید و شروع به ساختن کنید! بنابراین همراه با این پست، ما سیستم را به عنوان متنباز منتشر میکنیم و یک زمین بازی عمومی مستقر میکنیم.
کانتینر استریملاین را میتوان به صورت محلی اجرا کرد یا روی حساب کاربری خود مستقر کرد. این ابزار API ورکر را برای استفاده برنامه کنترلی شما صادر میکند.
همچنین یک برنامه ورکر نمونه با یک فرانتاند وب Astro وجود دارد که عملکرد استریملاین را با چند مورد استفاده رایج، از جمله پوششها، رمزگشایی زیرنویس، فیلترها و تصویر در تصویر نشان میدهد. قابلیت پروب (probe) وجود دارد که متریکهای عملکرد و ردیابی سیستم را فراهم میکند و میتواند برای اشکالزدایی سیستم هنگام توسعه ویژگیهای جدید مفید باشد. برنامه نمونه را میتوان روی یک سرور محلی Astro اجرا کرد، یا برای استقرار در پشت Cloudflare Access راهاندازی شده است، بنابراین میتوانید کنترل کنید چه کسی به نمونه استریملاین شما دسترسی دارد.
هر دو مخزن به عنوان متنباز در گیتهاب کلودفلر در دسترس هستند:
- https://github.com/cloudflare/streamline - موتور رسانه و خروجیهای پکیج برای برنامهها.
- https://github.com/cloudflare/streamline-demo - برنامه نمونه ورکر، فرانتاند Astro، پروفایلهای استقرار و ابزارهای دسترسی.
ما یک استقرار زمین بازی عمومی از برنامه نمونه را منتشر کردهایم. این نیز چیزی است که کاربر در صورت تمایل میتواند مستقر کند. این از پیکربندی دسترسی خود، یک هویت کانتینر به ازای هر کاربر تأییدشده، یک جلسه فعال به ازای هر کاربر، کنترل پذیرش جهانی، همزمانی، محدودیتهای رسانه و جلسه استفاده میکند و هیچ امکانی برای جایگزینی جلسه یک کاربر توسط کاربر دیگر وجود ندارد.
شما میتوانید زمین بازی عمومی را در آدرس زیر امتحان کنید:
قدم بعدی کجاست؟ (Where we go from here)
استریملاین یک راه برای ترکیب خدمات مدیریتشده موجود، مانند استریم، با اصول اولیه سطح پایینتر برای ساخت پایپلاینهای رسانهای بسیار قابل تنظیم را نشان میدهد. در این تکرار، استریملاین از پردازنده کانتینر برای پردازش رسانه استفاده میکند که یک گلوگاه را در کیفیتهای بالاتر یا نرخ فریم ایجاد میکند.
با نگاهی به آینده، ما هیجانزدهایم که ببینیم چگونه ما و جامعه توسعهدهندگان ما میتوانیم این معماری را برای ساخت پشتیبانی جدید برای پایپلاینهای بینایی کامپیوتر، پردازش رسانهای شتابیافته سختافزاری، تجربیات بلادرنگ با پروتکلهای نسل بعدی مانند WebRTC و MoQ، و در نهایت اصول رمزگذاری و رمزگشایی ویدیو به صورت بومی در ورکرها گسترش دهیم.
امروز، ما از شما دعوت میکنیم دمو میزبانیشده ما از استریملاین را بررسی کنید تا ببینید این ابزارها چقدر میتوانند قدرتمند باشند. از آنجا، پایگاههای کد متنباز ما را بررسی کنید تا ببینید چقدر آسان است که استریملاین را در حساب کاربری خود مستقر کنید و از آن برای ایجاد تجربیات خود استفاده کنید.
منبع: blog.cloudflare.com
