ভিডিও মাস্টারি — পর্ব ৭: লাইভ
RTMP থেকে SRT আর WHIP, রিয়েল-টাইম এনকোডিংয়ের সীমা, LL-HLS আসলে কীভাবে কাজ করে, লেটেন্সির বাজেট, DVR, ফেইলওভার, SCTE-35 আর বিজ্ঞাপন, আর মাল্টি-CDN স্টিয়ারিং।
RTMP থেকে SRT আর WHIP, রিয়েল-টাইম এনকোডিংয়ের সীমা, LL-HLS আসলে কীভাবে কাজ করে, লেটেন্সির বাজেট, DVR, ফেইলওভার, SCTE-35 আর বিজ্ঞাপন, আর মাল্টি-CDN স্টিয়ারিং।
এই পর্বে যা উল্টে যাবে
আগের ছয় পর্বের প্রায় সব কৌশল একটা জিনিসের উপর দাঁড়িয়ে ছিল — ভিডিওটা পুরোটা তোমার হাতে আছে।
পুরোটা হাতে আছে বলেই:
- ভিডিওকে টুকরো করে সমান্তরালে এনকোড করা যায় (পর্ব ৩)
- প্রতিটা শট বহুবার এনকোড করে সেরা ল্যাডার বেছে নেওয়া যায় (পর্ব ৪)
- সস্তা spot মেশিন ব্যবহার করা যায়, কারণ মেশিন মরলে ওই চাংকটা আবার চালালেই হয় (পর্ব ৫)
- এনকোডার lookahead করতে পারে, দুই pass চালাতে পারে
লাইভে এর একটাও পারবে না।
ফ্রেমটা এইমাত্র ক্যামেরা থেকে এল। পরের ফ্রেমটা এখনো ঘটেনি — তুমি জানোই না দৃশ্যটা কোন দিকে যাচ্ছে। কাজটা সমান্তরাল করা যায় না, কারণ ভবিষ্যৎ এখনো আসেনি। রিট্রাই করা যায় না, কারণ ততক্ষণে সময় পেরিয়ে গেছে। ব্যর্থ হলে দর্শক কালো স্ক্রিন দেখে — VOD-এর মতো “আরেকটু পরে আবার চেষ্টা করব” নেই।
লাইভ তাই আলাদা কোনো ফিচার না। এটা একই পাইপলাইন, কিন্তু সময়ের বাজেট শূন্য — আর সেই একটা পরিবর্তনই প্রতিটা সিদ্ধান্ত বদলে দেয়।
১. লেটেন্সির বাজেট — সেকেন্ডগুলো কোথায় যায়
“লেটেন্সি” মানে ঘটনাটা ঘটা আর দর্শকের স্ক্রিনে দেখা — এই দুইয়ের মাঝের সময়। একে বলে glass-to-glass (ক্যামেরার কাঁচ থেকে ফোনের কাঁচ)।
সাধারণ HLS-এ এটা সাধারণত ৩০ সেকেন্ডের মতো। কেন, সেটা ভাঙলে বোঝা যায় — আর ভাঙাটাই এই পর্বের সবচেয়ে দরকারি টেবিল:
| ধাপ | সাধারণ খরচ | কেন |
|---|---|---|
| ক্যামেরা ও এনকোডার বাফার | ০.৫–২ সেকেন্ড | এনকোডারকে কিছু ফ্রেম জমাতে হয় |
| contribution (ingest পর্যন্ত পৌঁছানো) | ০.৫–২ সেকেন্ড | নেটওয়ার্ক + ত্রুটি সামলানো |
| ট্রান্সকোড + প্যাকেজিং | ১–৩ সেকেন্ড | সেগমেন্ট পুরো না হলে লেখা যায় না |
| CDN-এ পৌঁছানো | ০.৫–২ সেকেন্ড | origin → edge |
| প্লেয়ারের বাফার | ১৫–২০ সেকেন্ড | এখানেই আসল খরচ |
লক্ষ করো, সবচেয়ে বড় অংশটা এনকোডিং না, নেটওয়ার্কও না — প্লেয়ার ইচ্ছা করে পিছিয়ে থাকে।
কারণ পর্ব ১-এ বলা: প্লেয়ার কয়েকটা সেগমেন্ট জমিয়ে না রাখলে নেট একটু কাঁপলেই ভিডিও আটকে যাবে। ৬ সেকেন্ডের সেগমেন্ট হলে তিনটা জমাতে গেলেই ১৮ সেকেন্ড।
তাই লেটেন্সি কমানোর পুরো খেলাটা আসলে একটাই প্রশ্ন: প্লেয়ারকে কম জমিয়ে রাখতে রাজি করানো যায় কীভাবে, অথচ বাফারিং না বাড়িয়ে?
তিনটা মোটামুটি স্তর আছে, আর প্রতিটার দাম আলাদা:
| স্তর | লেটেন্সি | প্রযুক্তি |
|---|---|---|
| সাধারণ HLS/DASH | ~৩০ সেকেন্ড | ৬ সেকেন্ডের সেগমেন্ট, কিছুই বিশেষ না |
| কম লেটেন্সি | ~৫–১০ সেকেন্ড | LL-HLS / LL-DASH |
| রিয়েল টাইম | ১ সেকেন্ডের নিচে | WebRTC |
সবচেয়ে দামি ভুলটা এখানেই হয়: “যত কম লেটেন্সি তত ভালো” ধরে নেওয়া। কম লেটেন্সি মানে ছোট বাফার, ছোট বাফার মানে বেশি বাফারিং। একটা লেকচার বা সিনেমার জন্য ৩০ সেকেন্ড পিছিয়ে থাকা কোনো সমস্যাই না — বরং মসৃণ চলাটাই আসল। নিলাম, খেলার স্কোর, বা ইন্টারঅ্যাকটিভ কিছু হলে তখন কম লেটেন্সির দাম আছে। আগে ঠিক করো তোমার আসলে কত লাগবে, তারপর তার দাম দাও।
২. Ingest — স্ট্রিমটা তোমার সার্ভারে আসবে কীভাবে
প্রথম ধাপ: সম্প্রচারকের যন্ত্র (OBS, ফোন, হার্ডওয়্যার এনকোডার) থেকে তোমার সার্ভারে ভিডিওটা পাঠানো। একে বলে contribution বা ingest — দর্শকের কাছে পাঠানোর (distribution) সাথে গুলিয়ে ফেলো না। দুটোর সমস্যাই আলাদা: contribution-এ একটা উৎস কিন্তু বিটরেট বিশাল; distribution-এ বিটরেট কম কিন্তু লক্ষ লক্ষ গন্তব্য।
চারটা প্রোটোকল বাস্তবে চলে।
RTMP — মরেও মরে না
RTMP জন্মেছিল Flash-এর জন্য। Flash মরে গেছে বহু আগে। RTMP তবু টিকে আছে এবং আজও সবচেয়ে বেশি ব্যবহৃত ingest প্রোটোকল।
কেন? কারণ সব কিছুই এটা বলতে পারে — OBS, প্রতিটা হার্ডওয়্যার এনকোডার, প্রতিটা ফোন অ্যাপ, প্রতিটা প্ল্যাটফর্ম। মডেলটাও সরল: একটা URL আর একটা stream key।
সীমাবদ্ধতা: TCP-র উপর চলে (তাই খারাপ নেটে হেড-অব-লাইন ব্লকিং), লেটেন্সি কয়েক সেকেন্ড, আর নতুন কোডেকের সমর্থন দুর্বল।
SRT — অনির্ভরযোগ্য নেটওয়ার্কের জন্য
SRT (Secure Reliable Transport) UDP-র উপর চলে আর হারানো প্যাকেট ARQ দিয়ে আবার চায়। মানে খারাপ নেটওয়ার্কে — মাঠ থেকে, মোবাইল কানেকশনে — এটা RTMP-র চেয়ে অনেক ভালো ধরে রাখে। এনক্রিপশন আর একটা নির্দিষ্ট latency buffer সেট করার সুবিধাও আছে।
Mux-এর ডকুমেন্টেশন থেকে একটা আসল উদাহরণ — খেয়াল করো কি-ফ্রেমের সেটিংটা:
ffmpeg \
-f lavfi -re -i testsrc=size=1920x1080:rate=30 \
-f lavfi -i "sine=frequency=1000:duration=3600" \
-c:v libx264 -x264-params keyint=120:scenecut=0 \
-preset superfast -b:v 5M -maxrate 6M -bufsize 3M -threads 4 \
-c:a aac \
-f mpegts 'srt://global-live.mux.com:6001?streamid={stream_key}&passphrase={srt_passphrase}' তিনটা জিনিস এখানে পর্ব ২-এর সরাসরি ধারাবাহিকতা:
keyint=120:scenecut=0— ৩০ fps-এ ১২০ মানে প্রতি ৪ সেকেন্ডে একটা কি-ফ্রেম, আরscenecut=0দিয়ে দৃশ্য বদলালেও বাড়তি কি-ফ্রেম বসানো বন্ধ। কারণ সেগমেন্টের সীমানা কি-ফ্রেমেই পড়তে হবে।-preset superfast— VOD-এ আমরা ধীর preset ব্যবহার করতাম ভালো কম্প্রেশনের জন্য। লাইভে সেই বিলাসিতা নেই।-maxrateআর-bufsize— পর্ব ১-এর VBV। লাইভে এটা ঐচ্ছিক না; বিটরেট হঠাৎ লাফালে contribution লিংকই ভেঙে যাবে।
RIST — ব্রডকাস্ট দুনিয়ার উত্তর
RIST একই সমস্যার (অনির্ভরযোগ্য নেটে নির্ভরযোগ্য পরিবহন) সমাধান, তবে ব্রডকাস্ট ইন্ডাস্ট্রির স্ট্যান্ডার্ড হিসেবে তৈরি। তুমি যদি টেলিভিশনের যন্ত্রপাতির সাথে কাজ না করো, সম্ভবত এটা লাগবে না।
WHIP — নতুনটা
WHIP (WebRTC-HTTP Ingestion Protocol) হলো WebRTC দিয়ে ingest করার একটা সরল HTTP-ভিত্তিক উপায়। এটা RFC 9725 হিসেবে প্রকাশিত হয়েছে ২০২৫-এর মার্চে — মানে এটা আর পরীক্ষামূলক না, স্ট্যান্ডার্ড।
মডেলটা ইচ্ছা করেই RTMP-র মতো রাখা হয়েছে — একটা URL আর একটা stream key — কিন্তু ভেতরে WebRTC, তাই লেটেন্সি সেকেন্ডের নিচে। OBS Studio v30 থেকে নেটিভভাবে WHIP পাঠাতে পারে, আর Cloudflare, AWS IVS, Dolby, Red5, Ant Media-সহ অনেকে WHIP endpoint দেয়।
তবে WHIP সব জায়গায় SRT-র বিকল্প না। ৪K HDR-এর মতো উঁচু, স্থির বিটরেটের contribution-এ SRT-ই এখনো নিরাপদ পছন্দ, কারণ WebRTC-র congestion control ওই ধরনের কাজের জন্য বানানো হয়নি — SRT-র ARQ-ভিত্তিক পুনরুদ্ধার সেখানে অনেক বেশি অনুমানযোগ্য।
কোনটা বাছবে
| পরিস্থিতি | পছন্দ |
|---|---|
| যে কেউ যেকোনো যন্ত্র থেকে পাঠাবে | RTMP (কারণ সবাই এটা পারে) |
| মাঠ থেকে, খারাপ/মোবাইল নেটে | SRT |
| ব্রাউজার থেকে সরাসরি, বা সেকেন্ডের নিচে লেটেন্সি | WHIP |
| ব্রডকাস্ট যন্ত্রপাতির সাথে | RIST বা SRT |
বাস্তবে বড় প্ল্যাটফর্মগুলো সবগুলোই নেয়, কারণ সম্প্রচারক কী পাঠাতে পারবে সেটা তুমি ঠিক করতে পারো না।
৩. লাইভ ট্রান্সকোডিং — যেখানে সব কৌশল বাতিল
স্ট্রিম ঢুকল। এবার ল্যাডার বানাতে হবে। কিন্তু এখানে VOD-এর প্রায় কিছুই খাটে না।
সমান্তরাল করা যায় না। পর্ব ৩–৫-এর পুরো চাংকিং কৌশলটা অচল, কারণ চাংক ২ এখনো ঘটেনি। একটাই মেশিনকে রিয়েল টাইমে চালিয়ে যেতে হবে — মানে এনকোডিং অবশ্যই রিয়েল টাইমের চেয়ে দ্রুত হতে হবে, নইলে পিছিয়ে পড়তে থাকবে আর কখনো ধরতে পারবে না।
পার-টাইটেল বা পার-শট নেই। কনটেন্টের জটিলতা বিশ্লেষণ করার জন্য কনটেন্টটা আগে থাকতে হয়। লাইভে ল্যাডার আগেই ঠিক করা থাকে। (এই কারণেই পর্ব ৬-এ দেখা গেছে Mux-এর premium টিয়ার VOD-তে 4K দেয় কিন্তু লাইভে 1080p-তে থামে।)
spot মেশিন ব্যবহার করা যায় না — অন্তত এনকোডিংয়ের জন্য না। মাঝপথে মেশিন কেড়ে নিলে স্ট্রিম মরে যাবে, আর “আবার চালাও” বলে কিছু নেই।
preset দ্রুত রাখতে হয়, তাই একই বিটরেটে ছবির মান VOD-এর চেয়ে খারাপ হবে। এটা মেনে নেওয়া ছাড়া উপায় নেই।
ফলাফল: ছোট ল্যাডার, হার্ডওয়্যার এনকোডার
দুটো ব্যবহারিক সিদ্ধান্ত এখান থেকেই আসে:
- ল্যাডার ছোট রাখো। VOD-এ ছয়-সাতটা ধাপ স্বাভাবিক। লাইভে তিন-চারটা, কারণ প্রতিটা ধাপ রিয়েল টাইমে এনকোড করতে হচ্ছে — একই মেশিনে, একই সাথে।
- হার্ডওয়্যার এনকোডার বিবেচনা করো। পর্ব ৩-এ আমরা বলেছিলাম হার্ডওয়্যার এনকোডিং একই বিটরেটে সফটওয়্যারের চেয়ে খারাপ দেখায়, তাই VOD-এ সাধারণত সফটওয়্যারই ভালো। লাইভে হিসাবটা উল্টো — এখানে নিশ্চিতভাবে রিয়েল টাইম ধরে রাখা কোয়ালিটির চেয়ে বেশি জরুরি।
passthrough — সবচেয়ে কম আলোচিত কৌশল
সম্প্রচারক তো ইতিমধ্যেই একটা এনকোড করা স্ট্রিম পাঠাচ্ছে (ধরো 1080p @ 5 Mbps)। ওই স্ট্রিমটাকে আবার এনকোড না করে সরাসরি ল্যাডারের সবচেয়ে উপরের ধাপ হিসেবে ব্যবহার করা যায় — শুধু সেগমেন্ট করে প্যাকেজ করতে হবে।
লাভ দুটোই: CPU বাঁচে, আর ওই ধাপে কোয়ালিটির কোনো ক্ষতি হয় না (কারণ পুনরায় এনকোড হচ্ছেই না)। নিচের ধাপগুলো তখন সোর্স থেকে বানানো হয়।
শর্ত: সম্প্রচারকের পাঠানো স্ট্রিমের কি-ফ্রেম ব্যবধান তোমার সেগমেন্টের সাথে মিলতে হবে। এই কারণেই প্রতিটা লাইভ প্ল্যাটফর্মের ডকুমেন্টেশনে “keyint এত রাখুন” লেখা থাকে — ওরা তোমার স্ট্রিমটা passthrough করতে চায়।
৪. প্যাকেজিং — প্লেলিস্ট যেটা বদলাতেই থাকে
VOD-এ প্লেলিস্ট একবার লেখা হয়, তারপর অপরিবর্তিত। লাইভে সেটাই মূল পার্থক্য: প্লেলিস্ট একটা চলন্ত জানালা।
প্রতিটা নতুন সেগমেন্ট তৈরি হলে সেটা তালিকার শেষে যোগ হয়, আর পুরনোগুলো শুরু থেকে বাদ পড়ে। প্লেয়ার কয়েক সেকেন্ড পরপর প্লেলিস্টটা আবার চায়।
এখানে দুটো সিদ্ধান্ত:
সেগমেন্টের দৈর্ঘ্য। ছোট সেগমেন্ট = কম লেটেন্সি, কিন্তু বেশি HTTP রিকোয়েস্ট আর বেশি ওভারহেড। ২ সেকেন্ড লাইভে সাধারণ; ৬ সেকেন্ড VOD-এ।
DVR উইন্ডো — প্লেলিস্টে কত সময়ের সেগমেন্ট রাখবে। এটাই ঠিক করে দর্শক কতটা পিছিয়ে যেতে পারবে। ৩০ সেকেন্ড রাখলে কেউ পাঁচ মিনিট আগের গোলটা দেখতে পারবে না। পুরো অনুষ্ঠান রাখলে স্টোরেজ আর origin-এর চাপ বাড়ে। খেলা বা লম্বা অনুষ্ঠানে সাধারণত ঘণ্টাখানেকের DVR রাখা হয়।
৫. LL-HLS — আসলে কীভাবে কাজ করে
“LL-HLS লেটেন্সি কমায়” — এটুকু সবাই বলে। ভেতরে আসলে চারটা আলাদা কৌশল, আর প্রতিটার নিজস্ব ট্যাগ আছে। স্পেসিফিকেশন থেকে একটা একটা করে দেখি, কারণ এগুলো না বুঝলে ডিবাগ করা অসম্ভব।
কৌশল ১: সেগমেন্টকে আরও ছোট টুকরোয় ভাঙা
মূল সমস্যা: ৬ সেকেন্ডের সেগমেন্ট পুরো শেষ না হলে প্লেলিস্টে লেখা যায় না। মানে জন্মের সাথে সাথেই ৬ সেকেন্ড দেরি।
সমাধান: সেগমেন্টটাকে partial segment বা “part”-এ ভাঙা — প্রতিটা হয়তো ২০০ মিলিসেকেন্ড। সেগমেন্ট শেষ হওয়ার অপেক্ষা না করে part গুলো একে একে প্রকাশ করা হয়।
#EXT-X-PART-INF:PART-TARGET=0.33334
...
#EXT-X-PART:DURATION=0.33334,URI="seg12.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="seg12.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="seg12.2.mp4"
#EXTINF:1.00000,
seg12.mp4 EXT-X-PART-INF-এর PART-TARGET বলে দেয় part গুলো সর্বোচ্চ কত লম্বা হতে পারে — স্পেক অনুযায়ী কোনো part এর চেয়ে লম্বা হতে পারবে না। INDEPENDENT=YES মানে ওই part-এ একটা স্বাধীন ফ্রেম আছে, অর্থাৎ প্লেয়ার চাইলে ওখান থেকেই শুরু করতে পারে।
কৌশল ২: পরেরটা কী আসছে, আগেই বলে দাও
EXT-X-PRELOAD-HINT দিয়ে সার্ভার বলে দেয় পরের part-এর URL কী হবে — তৈরি হওয়ার আগেই।
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="seg12.3.mp4" প্লেয়ার তখন ওই URL-এ রিকোয়েস্ট পাঠিয়ে বসে থাকতে পারে; জিনিসটা তৈরি হওয়ামাত্র সার্ভার উত্তর দেওয়া শুরু করে। মানে রাউন্ড ট্রিপের দেরিটা বাদ।
কৌশল ৩: ব্লকিং প্লেলিস্ট রিলোড
সাধারণ লাইভে প্লেয়ার বারবার প্লেলিস্ট চায় — “নতুন কিছু আছে? নতুন কিছু আছে?” বেশিরভাগ উত্তরই “না”। এটা অপচয়, আর নতুন জিনিসটা পেতেও গড়ে আধা পোল-ইন্টারভাল দেরি হয়।
LL-HLS-এ প্লেয়ার বলতে পারে “আমার কাছে ১২ নম্বর সেগমেন্টের ২ নম্বর part পর্যন্ত আছে; এর পরেরটা তৈরি হলে তবেই উত্তর দাও“:
GET /live.m3u8?_HLS_msn=12&_HLS_part=3 সার্ভার রিকোয়েস্টটা ধরে রাখে যতক্ষণ না ওই জিনিসটা তৈরি হয়। সার্ভার এই ক্ষমতার কথা জানায় EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES দিয়ে।
কৌশল ৪: প্লেলিস্টটা প্রতিবার পুরো না পাঠানো
লম্বা DVR উইন্ডো মানে বিশাল প্লেলিস্ট — যেটা প্রতি কয়েকশো মিলিসেকেন্ডে পুরোটা পাঠানো হাস্যকর।
Delta update: প্লেয়ার বলে “আমার কাছে পুরনোটা আছে, শুধু নতুন অংশ দাও”, আর সার্ভার পুরনো অংশটার বদলে একটা EXT-X-SKIP ট্যাগ পাঠায় যেখানে লেখা থাকে কতগুলো সেগমেন্ট বাদ দেওয়া হলো। সার্ভার CAN-SKIP-UNTIL দিয়ে জানায় কতদূর পর্যন্ত এভাবে বাদ দেওয়া যাবে — স্পেক বলছে এই মানটা টার্গেট দৈর্ঘ্যের অন্তত ছয় গুণ হতে হবে।
দুটো সংখ্যা যেগুলো ভুল হলে সব ভাঙে
স্পেকের এই দুটো মান লেটেন্সি আর স্থিতিশীলতার আসল নিয়ন্ত্রক:
HOLD-BACK— প্লেয়ার লাইভ প্রান্ত থেকে অন্তত কতটা পিছিয়ে থাকবে। টার্গেট দৈর্ঘ্যের অন্তত তিন গুণ হতে হবে, আর না দিলে ডিফল্টই তিন গুণ।PART-HOLD-BACK— কম-লেটেন্সি মোডে একই জিনিস, কিন্তু part-এর হিসাবে। PART-TARGET-এর অন্তত দ্বিগুণ হতে হবে, আর স্পেক বলছে তিন গুণ রাখাই উচিত।
এই দুটোই ব্যাখ্যা করে কেন LL-HLS-এ লেটেন্সি সাধারণত ৫ সেকেন্ডের নিচে নামে না: part যদি ৩৩৩ মিলিসেকেন্ড হয় আর PART-HOLD-BACK তিন গুণ হয়, প্লেয়ার এক সেকেন্ড পিছিয়ে; তার সাথে এনকোড, প্যাকেজিং আর CDN যোগ করলেই কয়েক সেকেন্ড।
সতর্কতা: LL-HLS সস্তা না
- origin-এর উপর চাপ বহু গুণ বাড়ে — ৬ সেকেন্ডে একটা রিকোয়েস্টের বদলে সেকেন্ডে তিনটা, প্রতিটা দর্শকের জন্য।
- CDN-কে এটা সমর্থন করতে হবে — বিশেষ করে ব্লকিং রিকোয়েস্ট ধরে রাখা আর অসম্পূর্ণ জিনিস chunked transfer-এ পাঠানো। সব CDN কনফিগারেশনে এটা এমনিতে চলে না।
- সব প্লেয়ার সমানভাবে করে না। কেউ LL-HLS-এর ট্যাগ উপেক্ষা করে সাধারণ HLS হিসেবেই চালাবে — যেটা অন্তত ভাঙবে না, কিন্তু লেটেন্সিও কমবে না।
৬. প্লেয়ার কীভাবে লাইভ প্রান্তের কাছে থাকে
একটা সূক্ষ্ম সমস্যা, যেটা লাইভে সবসময় আসে: প্লেয়ার একবার পিছিয়ে পড়লে নিজে নিজে আর সামনে আসে না।
ধরো নেট এক মুহূর্তের জন্য খারাপ হলো, প্লেয়ার ৩ সেকেন্ড বাফার করল। এখন সে লাইভ প্রান্ত থেকে ৩ সেকেন্ড বেশি পিছিয়ে — আর ভিডিও তো স্বাভাবিক গতিতেই চলছে, তাই এই ৩ সেকেন্ড চিরকাল থেকে যাবে।
সমাধান: সামান্য দ্রুত চালানো। প্লেয়ার যখন দেখে সে টার্গেটের চেয়ে বেশি পিছিয়ে, তখন প্লেব্যাক রেট সামান্য বাড়িয়ে দেয় (যেমন ১.০৫×) যতক্ষণ না ধরে ফেলে, তারপর আবার ১.০×-এ ফেরে। ৫% পার্থক্য কানে ধরা পড়ে না।
dash.js-এ এটা liveCatchup সেটিং — টার্গেট লেটেন্সি, সর্বোচ্চ drift, আর প্লেব্যাক রেটের সর্বনিম্ন-সর্বোচ্চ সীমা সেট করা যায়। hls.js-এ liveSyncDurationCount (লাইভ প্রান্ত থেকে কয়টা সেগমেন্ট পিছিয়ে থাকবে, ডিফল্ট ৩) আর liveMaxLatencyDurationCount দিয়ে একই জিনিস নিয়ন্ত্রণ করা হয়।
ডিবাগ করার সময় এটা মনে রেখো: “আমাদের লাইভে লেটেন্সি ৪০ সেকেন্ড” অভিযোগের সবচেয়ে সাধারণ কারণ সার্ভার না — দর্শক কোনো এক সময় বাফার করেছিল আর প্লেয়ার আর কখনো ধরতে পারেনি।
৭. ব্যর্থতা — লাইভে যা যা ভাঙে
VOD-এ ব্যর্থতা মানে “কাজটা আবার চালাও”। লাইভে ব্যর্থতা মানে দর্শক এখনই কালো স্ক্রিন দেখছে। তাই কৌশলগুলো আলাদা।
সম্প্রচারকের নেট কেটে গেল। সাথে সাথে স্ট্রিম শেষ ঘোষণা করা ঠিক না — মোবাইল নেটে দুই সেকেন্ডের বিচ্ছিন্নতা স্বাভাবিক। তাই একটা reconnect window রাখা হয়: এই সময়ের মধ্যে ফিরে এলে একই স্ট্রিম চলতে থাকে। পর্ব ৬-এ Mux-এর API-তে আমরা এটা দেখেছি — "reconnect_window": 60।
এই সময়টায় দর্শককে কী দেখাবে সেটাও সিদ্ধান্ত: শেষ ফ্রেমে আটকে থাকা, একটা “সংযোগ ফিরে আসছে” স্লেট, নাকি বিজ্ঞাপন।
একটাই ingest পয়েন্ট মানে একটাই ব্যর্থতার বিন্দু। গুরুত্বপূর্ণ অনুষ্ঠানে সম্প্রচারক দুটো আলাদা পথে একই স্ট্রিম পাঠায় (দুটো ISP, বা একটা ব্রডব্যান্ড একটা মোবাইল), আর সার্ভার প্রাথমিকটা মরলে ব্যাকআপে চলে যায়।
একই স্ট্রিম একাধিক জায়গায় পাঠানো (simulcast)। YouTube, Twitch, Facebook-এ একই সাথে পাঠানো — সম্প্রচারকের যন্ত্র থেকে তিনবার আপলোড করলে তার নেট শেষ। তাই কাজটা সার্ভার করে: একবার ingest নিয়ে বাকিদের কাছে ছড়িয়ে দেয়।
স্ট্রিম শেষ হলে রেকর্ডিং। লাইভ শেষ হলে জিনিসটা আপনাআপনি একটা VOD অ্যাসেট হয়ে যাওয়া উচিত। পর্ব ৬-এ Mux-এর new_asset_settings ঠিক এটাই করে। এখানে সূক্ষ্ম কাজটা হলো — লাইভের ল্যাডার ছোট আর preset দ্রুত ছিল, তাই ভালো প্ল্যাটফর্ম পরে ধীরে ধীরে VOD-এর মানে আবার এনকোড করে নেয়।
হঠাৎ দর্শক বিস্ফোরণ। পর্ব ৬-এ দেখা গেছে Mux Kubernetes বেছেছে ঠিক এই কারণে — লাইভে দর্শক সংখ্যা সেকেন্ডে শূন্য থেকে লাখে যেতে পারে। মনে রাখার মতো ব্যাপার: দর্শক বাড়লে এনকোডিংয়ের খরচ বাড়ে না (একবারই এনকোড হচ্ছে), বাড়ে ডেলিভারির খরচ। তাই লাইভে CDN-ই আসল স্কেলিং সমস্যা, এনকোডার না।
৮. বিজ্ঞাপন — SCTE-35, SSAI আর CSAI
এই অংশটা আগের পর্বগুলোয় ছিল না, অথচ বাণিজ্যিকভাবে সবচেয়ে গুরুত্বপূর্ণ।
বিরতি কোথায়, সেটা জানানো: SCTE-35
SCTE-35 হলো স্ট্রিমের ভেতরে বসানো একটা সংকেত — ব্রডকাস্ট দুনিয়ার পুরনো স্ট্যান্ডার্ড — যেটা বলে “এখানে একটা বিজ্ঞাপন বিরতি শুরু, এত সেকেন্ডের”।
টেলিভিশনে এই সংকেত দেখে স্থানীয় স্টেশন নিজের বিজ্ঞাপন ঢোকাত। স্ট্রিমিংয়ে একই সংকেত ব্যবহার হয়, শুধু ঢোকানোর কাজটা করে সফটওয়্যার।
দুটো পদ্ধতি
CSAI (client-side) — প্লেয়ার নিজে বিজ্ঞাপন সার্ভারের সাথে কথা বলে, বিজ্ঞাপনটা আলাদা করে নামায়, আর মূল ভিডিও থামিয়ে ওটা চালায়। বিজ্ঞাপনের ফরম্যাট সাধারণত VAST (একক বিজ্ঞাপন) বা VMAP (কোথায় কোথায় বিরতি)।
সুবিধা: ইন্টারঅ্যাকটিভ বিজ্ঞাপন সম্ভব, ক্লিক-ট্র্যাকিং সহজ। অসুবিধা: প্লেয়ারকে ভিডিও থামিয়ে অন্য জিনিস চালাতে হয় — বাফারিং হয়, আর অ্যাড ব্লকার সহজেই আটকে দেয়, কারণ বিজ্ঞাপন সার্ভারের ডোমেইন আলাদা।
SSAI (server-side) — বিজ্ঞাপনটা সার্ভারেই মূল স্ট্রিমের সাথে সেলাই করে দেওয়া হয়। প্লেয়ার কিছুই জানে না; সে একটাই ম্যানিফেস্ট দেখে যেখানে কনটেন্ট আর বিজ্ঞাপনের সেগমেন্ট পাশাপাশি সাজানো।
কাজটা করে একটা stitcher: সে SCTE-35 সংকেত দেখে, বিজ্ঞাপন সার্ভার থেকে সিদ্ধান্ত চায় (উত্তর আসে VAST/VMAP-এ), তারপর ম্যানিফেস্টটা নতুন করে লিখে দেয় — বিজ্ঞাপনের সেগমেন্টগুলো কনটেন্টের সেগমেন্টের মাঝখানে বসিয়ে, দুয়ের সীমানায় একটা EXT-X-DISCONTINUITY মার্কার দিয়ে।
#EXTINF:6.0,
content-0421.ts
#EXT-X-DISCONTINUITY
#EXTINF:6.0,
ad-creative-a-0.ts
#EXTINF:6.0,
ad-creative-a-1.ts
#EXT-X-DISCONTINUITY
#EXTINF:6.0,
content-0422.ts সুবিধা: বিরতিটা মসৃণ (প্লেয়ারের দিক থেকে এটা তো একই স্ট্রিমেরই ধারাবাহিকতা), আর অ্যাড ব্লকার কাজ করে না — কারণ সব সেগমেন্টের URL একই ডোমেইন থেকে আসছে, ব্লকারের কাছে আলাদা করার কোনো সংকেতই নেই।
অসুবিধা: অনেক জটিল। বিজ্ঞাপনের ভিডিওটাকে মূল কনটেন্টের এনকোডিং বৈশিষ্ট্যের সাথে মিলিয়ে ট্রান্সকোড করে রাখতে হয় (একই রেজলিউশন, একই কোডেক, একই ল্যাডার) — নইলে সেলাইয়ের জায়গায় প্লেয়ার হোঁচট খাবে। আর প্রতিটা দর্শকের ম্যানিফেস্ট আলাদা হয়ে যায়, মানে ম্যানিফেস্ট আর ক্যাশ করা যায় না।
EXT-X-DISCONTINUITYট্যাগটা এখানে কাকতালীয় না। এটা প্লেয়ারকে বলে “এর পরের অংশটা আগের অংশের ধারাবাহিকতা না — টাইমস্ট্যাম্প, রেজলিউশন, এমনকি কোডেকও বদলাতে পারে, ডিকোডারটা আবার সেট করে নাও”। পর্ব ১-এ PTS/DTS নিয়ে যা বলা হয়েছিল, এই ট্যাগটা তারই ব্যবহারিক ফল।
৯. একাধিক CDN — content steering
লাইভে CDN-ই আসল স্কেলিং সমস্যা, তাই বড় ইভেন্টে সবাই একাধিক CDN ব্যবহার করে। কিন্তু কোন দর্শক কোন CDN থেকে নেবে, সেটা ঠিক করবে কে?
পুরনো উপায়গুলো সবই আনাড়ি — DNS দিয়ে ঘোরানো (ধীর, আর সেশনের মাঝপথে বদলানো যায় না), অথবা প্লেয়ারে কাস্টম প্লাগইন বসানো (প্রতিটা প্ল্যাটফর্মে আলাদা কাজ)।
Content Steering এই সমস্যার স্ট্যান্ডার্ড সমাধান, আর এখন HLS আর DASH দুটোতেই আছে। কাজটা সরল: প্লেয়ার নিয়মিত একটা steering server-কে জিজ্ঞেস করে, আর সার্ভার একটা ছোট JSON (“steering manifest”) ফেরত দেয় যেখানে বলা থাকে এখন কোন CDN ব্যবহার করা উচিত, অগ্রাধিকারের ক্রমসহ।
লাভটা হলো — সিদ্ধান্তটা সেশন ধরে ধরে, চলার মাঝপথেও বদলানো যায়, কোনো DNS বা প্লাগইন ছাড়াই। একটা CDN খারাপ করতে শুরু করলে দর্শকদের সরিয়ে নেওয়া যায়। DASH-IF-এর সংস্করণটা ETSI স্ট্যান্ডার্ড হিসেবে প্রকাশের পথে, আর সার্ভার-ক্লায়েন্ট স্তরে এটা HLS-এর স্টিয়ারিংয়ের সাথে সামঞ্জস্যপূর্ণ — মানে একই স্টিয়ারিং সার্ভার দুটো প্রোটোকলকেই চালাতে পারে।
hls.js-এ এর জন্য একটা আলাদা contentSteeringController আছে; মানে ব্রাউজারে এটা আজই ব্যবহারযোগ্য।
১০. লাইভের চেকলিস্ট
Ingest
- RTMP তো রাখতেই হবে; SRT দাও খারাপ নেটের জন্য, WHIP দাও ব্রাউজার/কম লেটেন্সির জন্য
- কি-ফ্রেম ব্যবধান নির্দিষ্ট করে দাও (
scenecut=0সহ) — নইলে সেগমেন্ট করা ভাঙবে - VBV (
maxrate,bufsize) বাধ্যতামূলক - reconnect window, আর ওই সময়ে কী দেখাবে সেটা ঠিক করা
- গুরুত্বপূর্ণ ইভেন্টে দ্বিতীয় ingest পথ
ট্রান্সকোড
- ল্যাডার ছোট (৩–৪ ধাপ), আগে থেকেই নির্ধারিত
- preset দ্রুত; দরকার হলে হার্ডওয়্যার এনকোডার
- passthrough ব্যবহার করো যেখানে সম্ভব
- রিয়েল টাইম ধরে রাখতে পারছে কিনা তার অ্যালার্ম
প্যাকেজিং ও ডেলিভারি
- সেগমেন্ট ২ সেকেন্ড, DVR উইন্ডো ঠিক করা
- LL-HLS লাগবে কিনা আগে ঠিক করো — লাগলে origin আর CDN দুটোকেই প্রস্তুত করো
-
HOLD-BACK/PART-HOLD-BACKস্পেকের ন্যূনতম মানের নিচে নামিও না - একাধিক CDN হলে content steering
পরিচালনা
- glass-to-glass লেটেন্সি মাপো, শুধু সার্ভারের দিকটা না
- প্লেয়ার লাইভ প্রান্ত থেকে কতটা পিছিয়ে, সেটা মাপো (catch-up কাজ করছে কিনা)
- স্ট্রিম শেষে VOD অ্যাসেট, আর পরে ভালো মানে পুনঃএনকোড
- বিজ্ঞাপন থাকলে: বিজ্ঞাপনের ট্রান্সকোড মূল ল্যাডারের সাথে মেলে কিনা
শেষ কথা
লাইভ নতুন কোনো বিজ্ঞান না — একই ফ্রেম, একই কোডেক, একই সেগমেন্ট, একই ল্যাডার। যা বদলায় সেটা হলো তোমার হাতে সময় নেই, আর সেই একটা শর্ত থেকে বাকি সব সিদ্ধান্ত বেরিয়ে আসে: সমান্তরালতা যায়, পার-টাইটেল যায়, spot মেশিন যায়, ধীর preset যায়।
আর সবচেয়ে বেশি যে ভুলটা হয়, সেটা কারিগরি না — প্রয়োজনের চেয়ে কম লেটেন্সি চাওয়া। ৩০ সেকেন্ড পিছিয়ে মসৃণভাবে চলা একটা লেকচার, ৫ সেকেন্ড পিছিয়ে বারবার আটকানো লেকচারের চেয়ে ভালো। লেটেন্সি কমানোর দাম আছে — origin-এ, CDN-এ, প্লেয়ারে, আর ডিবাগ করার সময়ে।
সূত্র
- RFC 9725 — WebRTC-HTTP Ingestion Protocol (WHIP) — মার্চ ২০২৫
- HTTP Live Streaming 2nd Edition (draft-pantos-hls-rfc8216bis) — LL-HLS-এর সব ট্যাগ ও ন্যূনতম মান
- Mux — Use SRT to live stream ও Reduce live stream latency
- dash.js low latency ও liveCatchup সেটিংস
- hls.js API —
liveSyncDurationCount,contentSteeringController - DASH-IF / HLS Content Steering
পরের পর্বে — প্লেয়ার। যেখানে এই পুরো সিস্টেমটা শেষমেশ সত্যি হয় বা মিথ্যা হয়ে যায়।