Skip to content

প্লেয়ার ডিবাগিং প্লেবুক

আন্দাজ না করে লেয়ার ধরে ধরে — কোন প্লেব্যাক পথ চলছে, নেটওয়ার্ক, ম্যানিফেস্ট, কোডেক ও MSE, DRM, বাফার ও ABR, রেন্ডারিং, ডিভাইস। সাথে লক্ষণ থেকে সমাধানের পূর্ণ ক্যাটালগ আর একটা পরীক্ষা করা কনসোল স্নিপেট।

গল্পে বুঝি

ধানমন্ডির একটা ফ্ল্যাটের ড্রয়িংরুমের TV চলছে না। বাড়ির মালিক রুশদ ইলেকট্রিশিয়ান হাইসামকে ডাকলেন, আর হাইসাম আসার আগেই নিজে TV-টা দুবার বন্ধ-চালু করেছেন, রিমোটের ব্যাটারি বদলেছেন, আর পাশের দোকান থেকে নতুন একটা প্লাগ কিনে এনেছেন। কিছুই হয়নি। হাইসাম এসে প্রথমে TV ছুঁলেন না। তিনি জিজ্ঞেস করলেন, “ফ্ল্যাটের বাকি লাইট-ফ্যান চলছে? শুধু এই ঘরে, নাকি সব ঘরে? কবে থেকে? শেষ কী বদলানো হয়েছিল?”

উত্তর শুনে তিনি নিচে গেলেন মিটারের কাছে। মিটারে বিদ্যুৎ আসছে। তারপর ফ্ল্যাটের মেইন ব্রেকার: অন। তারপর ডিস্ট্রিবিউশন বোর্ড, যেখানে প্রতিটা ঘরের আলাদা ব্রেকার: ড্রয়িংরুমেরটা অন। তারপর দেয়ালের সুইচবোর্ড, টেস্টার দিয়ে: সুইচের আগে বিদ্যুৎ আছে, পরে নেই। সুইচটা ভেতরে পুড়ে গেছে। নতুন সুইচ লাগাতেই TV চলল। পুরো কাজে লাগল বিশ মিনিট, আর তার পনেরো মিনিট গেল কোথায় সমস্যা নেই সেটা নিশ্চিত হতে।

যাওয়ার আগে হাইসাম একটা কথা বললেন: “আপনি TV দিয়ে শুরু করেছিলেন, কারণ TV-টাই চোখে পড়ে। কিন্তু TV হলো লাইনের শেষ মাথা। আমি শুরু করি যেখান থেকে বিদ্যুৎ আসে, আর প্রতিটা ধাপে টেস্টার লাগাই। যে ধাপের আগে আছে কিন্তু পরে নেই, সমস্যা সেখানেই।” তিনি আরও বললেন, পাশের ফ্ল্যাটের ফাতিমার AC নাকি শুধু গরমের দুপুরে বন্ধ হয়, আর সেটা একদম আলাদা সমস্যা: ওই মডেলের AC-র নিজের একটা স্বভাব, ওয়্যারিংয়ের দোষ নয়।

মিলিয়ে নিই: রুশদের TV বন্ধ-চালু করা হলো পেজ রিফ্রেশ আর ক্যাশ ক্লিয়ার করে দেখা, যা কখনো কখনো কাজ করে কিন্তু কিছুই শেখায় না। “বাকি ঘর চলছে? কবে থেকে? কী বদলেছে?” হলো লক্ষণ সংগ্রহ। মিটার হলো নেটওয়ার্ক আর CDN, মেইন ব্রেকার ম্যানিফেস্ট আনা আর CORS, ডিস্ট্রিবিউশন বোর্ড ম্যানিফেস্টের ভেতরটা, ওয়্যারিং কোডেক আর MSE append, সুইচ DRM, সকেট বাফার আর ABR, আর TV নিজে রেন্ডারিং ও আউটপুট (HDCP, কালো স্ক্রিন)। টেস্টার হলো DevTools, media-internals, প্লেয়ারের ডিবাগ লগ। আর ফাতিমার AC হলো ডিভাইসের নিজস্ব স্বভাব: স্মার্ট TV বা পুরনো ফোনের সীমাবদ্ধতা, যা পুরো সিস্টেমের দোষ নয়। এই চ্যাপ্টার হাইসামের পদ্ধতিটা প্লেয়ারের জন্য লিখে রাখে।

প্রথম প্রশ্ন: কোন প্লেব্যাক পথ চলছে?

কোনো কমান্ড চালানোর আগে জানতে হবে ব্রাউজার আসলে কোন পথে ভিডিও চালাচ্ছে, কারণ তিনটা পথের সমস্যা আর টুল সম্পূর্ণ আলাদা।

পথকীভাবে চিনবেনকে দায়িত্বে
নেটিভ (video.src সরাসরি .m3u8 বা .mp4)video.currentSrc একটা সাধারণ URLব্রাউজারের নিজের প্লেয়ার; JavaScript লাইব্রেরির লগ এখানে কিছুই বলবে না
MSE (hls.js, Shaka, dash.js)video.currentSrc শুরু হয় blob: দিয়েলাইব্রেরি; তার ডিবাগ লগ আর ইভেন্টই মূল সূত্র
EME (DRM, নেটিভ বা MSE-র উপর)video.mediaKeys আছেলাইসেন্স সার্ভার, CDM আর ডিভাইসের নিরাপত্তা স্তর

Chrome এখন HLS নেটিভ চালায়, আর এটা পুরনো অনেক কোডের আচরণ বদলে দিয়েছে। অনেক বছর ধরে নিয়ম ছিল: শুধু Safari .m3u8 নেটিভ চালায়, বাকি সব ব্রাউজারে hls.js লাগে। তাই অনেক পেজ এভাবে লেখা: “যদি canPlayType('application/vnd.apple.mpegurl') কিছু ফেরত দেয়, নেটিভ চালাও।” Mux-এর ২০২৫ সালের অক্টোবরের ইনসিডেন্ট রিপোর্ট অনুযায়ী Chrome 141-এ কিছু ইউজারের কাছে আর 142-এ ডিফল্টভাবে নেটিভ HLS চালু হয়েছে। এই চ্যাপ্টারের জন্য Chrome 155-এ পরীক্ষা করে দেখা গেছে canPlayType ফেরত দেয় "maybe" আর video.src = 'master.m3u8' সরাসরি চলে। ফলে ওই পুরনো চেক এখন Chrome-কেও নেটিভ পথে পাঠায়। তখন hls.js-এর ABR, CMCD, লেভেলের ইভেন্ট, আপনার অ্যানালিটিক্সের রেন্ডিশন ডেটা, সব চুপচাপ উধাও। Mux সেই সময় একটা Chrome বাগের কারণে কোড 3 বা 4-এর এরর বাড়তে দেখেছিল, আর MSE পথকে অগ্রাধিকার দেওয়ার পরামর্শ দিয়েছিল। আপনার কোডে চেকের ক্রম দেখুন: MSE থাকলে আগে MSE, নেটিভ শুধু যেখানে MSE নেই। (২০২৬ সালের অক্টোবর অনুযায়ী; Chrome-এর রিলিজ নোট আর chromestatus দেখে নিশ্চিত হোন।)

টুলবক্স

টুলকোথায়কী দেখায়
DevTools Media প্যানেলChrome DevTools → More tools → Mediaপ্রতিটা প্লেয়ারের প্রপার্টি, ইভেন্ট, মেসেজ লগ, বাফারের টাইমলাইন; JSON হিসেবে এক্সপোর্ট
chrome://media-internalsChrome/Edge-এর ঠিকানা বারেএকই ধরনের তথ্য, সব ট্যাবের প্লেয়ার একসাথে; ডিকোডারের নাম আর হার্ডওয়্যার ডিকোড হচ্ছে কিনা
DevTools Networkসব ব্রাউজারেম্যানিফেস্ট, সেগমেন্ট, কী, লাইসেন্স রিকোয়েস্ট; স্ট্যাটাস, CORS এরর, সময়
hls.js ডিবাগnew Hls({ debug: true })প্রতিটা লোড, পার্স, append, লেভেল বদল, এরর কনসোলে
Shaka ডিবাগডিবাগ বিল্ড লোড করে লগ লেভেল বাড়ানএকই ধরনের বিস্তারিত লগ
Safari Web InspectorSafari → Develop মেনু; iPhone USB দিয়ে যুক্ত করে একই মেনু থেকেiOS-এর আসল ডিভাইসের কনসোল আর নেটওয়ার্ক
adb logcatAndroid, USB ডিবাগিং চালু করেনেটিভ অ্যাপের প্লেয়ারের লগ; Media3-তে EventLogger যোগ করলে প্রতিটা ইভেন্ট
Apple mediastreamvalidatorApple-এর HTTP Live Streaming Tools প্যাকেজ (Apple Developer-এর ডাউনলোড পেজ থেকে)একটা HLS স্ট্রিম Apple-এর নিয়ম মানে কিনা
curl, ffprobeটার্মিনালম্যানিফেস্টের হেডার আর বডি; একটা সেগমেন্টের ভেতরে কী আছে

DevTools-এর Media প্যানেল খোলার পথ Chrome-এর ডকস থেকে যাচাই করা। Apple-এর টুলের পেজ এই চ্যাপ্টার লেখার সময় পড়া যায়নি, তাই প্যাকেজের নাম আর ডাউনলোডের জায়গা Apple Developer সাইটে নিজে মিলিয়ে নিন (২০২৬ সালের অক্টোবর অনুযায়ী)।

সাত লেয়ারের পদ্ধতি

প্রতিটা লেয়ারে একটা প্রশ্ন। প্রশ্নের উত্তর “হ্যাঁ, ঠিক আছে” না হওয়া পর্যন্ত পরের লেয়ারে যাবেন না।

লেয়ার ১: নেটওয়ার্ক আর CORS। ম্যানিফেস্ট আর প্রথম সেগমেন্ট কি 200 দিয়ে আসছে, আর ব্রাউজার কি সেগুলো পড়তে পারছে? Network প্যানেলে লাল রিকোয়েস্ট বা কনসোলে “blocked by CORS policy” থাকলে এখানেই থামুন। টার্মিনাল থেকে একই URL curl -sI দিয়ে দেখুন; সেখানে চললে আর ব্রাউজারে না চললে সমস্যা প্রায় নিশ্চিতভাবে CORS, কারণ curl CORS মানে না। CDN-এর দিকের সমস্যা হলে CDN ডিবাগিং প্লেবুক-এ যান।

curl -sI -H 'Origin: https://baytalhikma.org' https://cdn.cordoba.example/v/42/master.m3u8 | grep -iE '^(HTTP|access-control|content-type|cache-control|age)'
HTTP/2 200
content-type: application/vnd.apple.mpegurl
access-control-allow-origin: https://baytalhikma.org
cache-control: public, max-age=60
age: 12

(উদাহরণ।) access-control-allow-origin না থাকলে বা অন্য অরিজিন দেখালে ব্রাউজার রেসপন্স ফেলে দেবে, যদিও স্ট্যাটাস 200।

লেয়ার ২: ম্যানিফেস্ট ঠিক আছে কি? ম্যানিফেস্ট খুলে পড়ুন। master-এ CODECS আছে? media playlist-এ EXT-X-TARGETDURATION কোনো সেগমেন্টের চেয়ে ছোট নয় তো? লাইভে EXT-X-MEDIA-SEQUENCE বাড়ছে? সেগমেন্টের URI আপেক্ষিক হলে কোথায় গিয়ে পড়ছে? Apple ডিভাইসে সমস্যা হলে mediastreamvalidator চালান।

লেয়ার ৩: কোডেক আর MSE append। ব্রাউজার কি এই কোডেক চালাতে পারে, আর append কি সফল হচ্ছে? কনসোলে MediaSource.isTypeSupported('video/mp4; codecs="…"') দিয়ে ম্যানিফেস্টের ঠিক কোডেক স্ট্রিংটা পরীক্ষা করুন। media-internals-এ append বা ডিমাক্সের এরর খুঁজুন। hls.js-এ bufferAppendError বা MANIFEST_INCOMPATIBLE_CODECS_ERROR এই লেয়ারের।

লেয়ার ৪: DRM। কী সিস্টেম কি পাওয়া গেছে (requestMediaKeySystemAccess সফল?), লাইসেন্স রিকোয়েস্ট গেছে আর 200 এসেছে? লাইসেন্স সার্ভারের এররের বডি পড়ুন, ওখানেই সাধারণত আসল কারণ লেখা থাকে। DRM চ্যাপ্টার-এ লাইসেন্স ফ্লো বিস্তারিত।

লেয়ার ৫: বাফার আর ABR। প্লেয়ার কি আটকে আছে কারণ ডেটা আসছে না, নাকি ডেটা আছে কিন্তু প্লেহেড ভুল জায়গায়? নিচের স্নিপেট বা Media প্যানেলের টাইমলাইনে buffered আর currentTime তুলনা করুন। ABR কোন লেভেলে আছে আর থ্রুপুট কত মাপছে?

লেয়ার ৬: রেন্ডারিং আর আউটপুট। ডেটা ডিকোড হচ্ছে (totalVideoFrames বাড়ছে) কিন্তু স্ক্রিন কালো? তাহলে সমস্যা আউটপুটে: HDCP, হার্ডওয়্যার ডিকোডার, CSS (ভিডিওর উপর কোনো এলিমেন্ট), বা ভিডিওর আকার শূন্য।

লেয়ার ৭: ডিভাইসের স্বভাব। উপরের সব ঠিক, কিন্তু শুধু একটা ডিভাইসে, একটা OS ভার্সনে, একটা TV ব্র্যান্ডে সমস্যা? তাহলে ওই ডিভাইসের সীমা: মেমরি, পুরনো ব্রাউজার ইঞ্জিন, সমর্থিত কোডেক লেভেল, বা অ্যাপের নিজস্ব নিয়ম (মোবাইল ও TV চ্যাপ্টার)।

কোথা থেকে শুরু করবেন

একটা কনসোল স্নিপেট

যেকোনো পেজের কনসোলে পেস্ট করুন। পেজের প্রতিটা video এলিমেন্টের অবস্থা এক নজরে দেখায়, আর পেজ যদি hls.js ইনস্ট্যান্স window.hls-এ রাখে, লেভেলগুলোও। কোনো লাইব্রেরি লাগে না।

(() => {
	const RS = ['HAVE_NOTHING', 'HAVE_METADATA', 'HAVE_CURRENT_DATA', 'HAVE_FUTURE_DATA', 'HAVE_ENOUGH_DATA'];
	const NS = ['NETWORK_EMPTY', 'NETWORK_IDLE', 'NETWORK_LOADING', 'NETWORK_NO_SOURCE'];
	const ME = ['', 'MEDIA_ERR_ABORTED', 'MEDIA_ERR_NETWORK', 'MEDIA_ERR_DECODE', 'MEDIA_ERR_SRC_NOT_SUPPORTED'];
	const ranges = (r) => Array.from({ length: r.length }, (_, i) => `${r.start(i).toFixed(2)}-${r.end(i).toFixed(2)}`).join(', ') || 'none';
	document.querySelectorAll('video').forEach((v, n) => {
		const b = v.buffered, t = v.currentTime;
		let ahead = 0;
		for (let i = 0; i < b.length; i++) if (t >= b.start(i) && t <= b.end(i)) ahead = b.end(i) - t;
		const q = v.getVideoPlaybackQuality?.();
		console.log(`video #${n}`, {
			src: v.currentSrc.slice(0, 80) || '(none)',
			mse: v.currentSrc.startsWith('blob:'),
			drm: Boolean(v.mediaKeys),
			readyState: RS[v.readyState],
			networkState: NS[v.networkState],
			error: v.error ? `${ME[v.error.code]} ${v.error.message}` : 'none',
			paused: v.paused, ended: v.ended, seeking: v.seeking,
			time: `${t.toFixed(2)} / ${v.duration}`,
			rate: v.playbackRate, muted: v.muted, volume: v.volume,
			size: `${v.videoWidth}x${v.videoHeight}`,
			buffered: ranges(b), aheadSec: +ahead.toFixed(2), seekable: ranges(v.seekable),
			frames: q ? `${q.droppedVideoFrames} dropped of ${q.totalVideoFrames}` : 'n/a',
			textTracks: Array.from(v.textTracks, (tt) => `${tt.kind}:${tt.language}:${tt.mode}`).join(' ') || 'none'
		});
	});
	const h = window.hls; // hls.js instance, if the page exposes one
	if (h?.levels) {
		console.table(h.levels.map((l, i) => ({ level: i, height: l.height, kbps: Math.round(l.bitrate / 1000), codecs: `${l.videoCodec},${l.audioCodec}`, current: i === h.currentLevel, loading: i === h.nextLoadLevel })));
		console.log('hls.js estimate kbps', Math.round(h.bandwidthEstimate / 1000), 'live latency', h.latency);
	}
})();

আগের চ্যাপ্টারের ছোট প্লেয়ারের উপর হেডলেস Chrome-এ চালানো আসল আউটপুট:

video #0 {
 "src": "blob:http://127.0.0.1:8765/1620a585-abea-41a0-9226-e05d49654d79",
 "mse": true,
 "drm": false,
 "readyState": "HAVE_ENOUGH_DATA",
 "networkState": "NETWORK_LOADING",
 "error": "none",
 "paused": false,
 "time": "3.75 / Infinity",
 "size": "640x360",
 "buffered": "0.00-23.96",
 "aheadSec": 20.2,
 "seekable": "0.00-23.96",
 "frames": "0 dropped of 116",
 "textTracks": "none"
}

এই আউটপুটটা একটা আসল বাগ ধরেছিল: VOD ভিডিওর duration ছিল Infinity আর seekable থেমে ছিল বাফারের শেষে, অর্থাৎ seek বার দিয়ে ভিডিওর শেষ অংশে যাওয়াই যেত না। প্লেয়ার MediaSource.duration সেট করছিল না। ঠিক করার পর একই স্নিপেট দেখাল "time": "3.78 / 30" আর "seekable": "0.00-30.00"। স্নিপেটের প্রতিটা লাইন এরকম একটা প্রশ্নের উত্তর দেয়, তাই অভিযোগ এলে প্রথমে এটা চালিয়ে আউটপুটটা টিকিটে জুড়ে দিন।

কীভাবে পড়বেন: readyState HAVE_METADATA-তে আটকে থাকা মানে মেটাডেটা এসেছে কিন্তু প্রথম ফ্রেমের ডেটা নেই। aheadSec শূন্য অথচ buffered খালি নয় মানে প্লেহেড বাফারের বাইরে। frames বাড়ছে অথচ স্ক্রিন কালো মানে লেয়ার ৬। mse: false অথচ আপনার পেজ hls.js ব্যবহার করে বলে জানেন, মানে আপনি আসলে নেটিভ পথে আছেন।

লক্ষণ থেকে সমাধান: পূর্ণ ক্যাটালগ

শুরুই হয় না

লক্ষণসম্ভাব্য কারণনিশ্চিত হবেন যেভাবেসমাধান
প্লে চাপলে কিছুই হয় না, কোনো এরর নেইঅটোপ্লে আটকেছে, বা play()-এর প্রত্যাখ্যান কেউ ধরেনিকনসোলে NotAllowedError; video.play()-এর Promise-এ .catch আছে কিনামিউট করে অটোপ্লে (Chrome-এ সবসময় অনুমোদিত), নয়তো প্রত্যাখ্যান ধরে প্লে বাটন দেখান
স্পিনার ঘোরে, Network-এ ম্যানিফেস্ট লালCORS, টোকেনের মেয়াদ শেষ, ভুল URLNetwork-এ স্ট্যাটাস আর কনসোলের CORS বার্তা; curl -sI -H 'Origin: …'CDN-এ Access-Control-Allow-Origin; টোকেন নতুন করে নেওয়া
ম্যানিফেস্ট আসে, সেগমেন্ট বা কী-তে CORS এররম্যানিফেস্ট আর সেগমেন্ট আলাদা হোস্টে, একটায় CORS নেইNetwork-এ কোন রিকোয়েস্ট লালসেগমেন্ট, init, কী, ক্যাপশন, সবার হোস্টে একই CORS নিয়ম
MEDIA_ERR_SRC_NOT_SUPPORTED (কোড 4)ব্রাউজার এই ফরম্যাট নেটিভ চালায় না; বা ভুল Content-Type; বা সেগমেন্টের বদলে একটা HTML এরর পেজস্নিপেটে mse; curl -sI দিয়ে content-type; রেসপন্সের প্রথম বাইটনেটিভ চালাতে না পারলে MSE লাইব্রেরি; সার্ভারের MIME টাইপ ঠিক করা
hls.js: MANIFEST_INCOMPATIBLE_CODECS_ERRORম্যানিফেস্টের কোনো রেন্ডিশনের কোডেক এই ব্রাউজার চালায় নাম্যানিফেস্টের CODECS নিয়ে MediaSource.isTypeSupportedসমর্থিত কোডেকে একটা রেন্ডিশন রাখুন (সাধারণত H.264)
Safari-তে MSE পথে sourceopen কখনো আসে নাManagedMediaSource সক্রিয় হয় শুধু disableRemotePlayback = true হলে বা AirPlay-এর জন্য একটা HLS source থাকলে (MDN)কনসোলে sourceopen লিসেনার কখনো ফায়ার করে কিনাvideo.disableRemotePlayback = true, অথবা বিকল্প HLS source দিন
iPhone-এ ভিডিও সাথে সাথে পুরো স্ক্রিনে চলে যায় বা চলেই নাplaysinline নেই; বা পুরনো iPhone-এ MSE নেইমার্কআপ দেখুন; 'ManagedMediaSource' in window আর 'MediaSource' in windowplaysinline যোগ করুন; MSE না থাকলে নেটিভ HLS
প্রথম ফ্রেম আসতে অনেক দেরিপ্রথম সেগমেন্ট বড়, শুরুতে উঁচু রেন্ডিশন, DRM লাইসেন্স ধীর, CDN MISSNetwork-এর waterfall: ম্যানিফেস্ট → init → প্রথম সেগমেন্ট → লাইসেন্সনিচু রেন্ডিশন থেকে শুরু, ছোট প্রথম সেগমেন্ট, লাইসেন্স আগেভাগে (স্টার্টআপ চ্যাপ্টার)

শব্দ আছে, ছবি নেই (বা উল্টো)

লক্ষণসম্ভাব্য কারণনিশ্চিত হবেন যেভাবেসমাধান
শব্দ আছে, স্ক্রিন কালো, frames বাড়ছে নাভিডিও ট্র্যাক ডিকোড হচ্ছে না: প্রোফাইল বা লেভেল ডিভাইসের সীমার বাইরেmedia-internals-এ ভিডিও ডিকোডারের এরর; ffprobe-এ প্রোফাইল ও লেভেলডিভাইসের সীমার ভেতরে একটা রেন্ডিশন; ম্যানিফেস্টের CODECS সঠিক লিখুন
শব্দ আছে, স্ক্রিন কালো, frames বাড়ছেডিকোড হচ্ছে কিন্তু দেখানো যাচ্ছে না: HDCP, CSS, ভিডিওর আকার শূন্যস্নিপেটে size আর frames; Elements-এ ভিডিওর উপরে কিছু আছে কিনানিচের HDCP সারি দেখুন; CSS ঠিক করুন
কিছু ডিভাইসে শুধু শব্দ, কিছুতে ঠিকউঁচু প্রোফাইল (High 4.2, 10-bit, HEVC) পুরনো ডিভাইস চালায় নাডিভাইস ধরে এরর ভাগ করুন; ওই ডিভাইসে isTypeSupportedল্যাডারের নিচে একটা সর্বজনীন রেন্ডিশন রাখুন
ছবি আছে, শব্দ নেইঅডিও কোডেক অসমর্থিত (যেমন AC-3), মিউট, বা আলাদা অডিও গ্রুপ লোড হয়নিস্নিপেটে muted, volume; Network-এ অডিও সেগমেন্ট আসছে কিনাAAC রেন্ডিশন রাখুন; অডিও গ্রুপের URI দেখুন
শব্দ আর ছবি সিঙ্কে নেইপ্যাকেজিংয়ে অডিও আর ভিডিওর শুরুর টাইমস্ট্যাম্প আলাদা, VFR সোর্স, এডিট লিস্ট উপেক্ষাদুটো ট্র্যাকের প্রথম টাইমস্ট্যাম্প ffprobe -show_packets দিয়ে তুলনাপ্যাকেজারে দুটো ট্র্যাক একই সময় থেকে শুরু; সোর্স CFR-এ রূপান্তর

চলতে চলতে আটকায়

লক্ষণসম্ভাব্য কারণনিশ্চিত হবেন যেভাবেসমাধান
বারবার রিবাফারথ্রুপুট রেন্ডিশনের চেয়ে কম, ABR খুব আশাবাদী, CDN ধীরQoE ডেটায় ওই সেশন (চ্যাপ্টার ১১); CMCD sid দিয়ে CDN লগABR-এর নিরাপত্তা গুণক বাড়ান; CDN-এর MISS দেখুন
লাইভে অনন্ত স্পিনার, এনকোডার চলছেপ্লেলিস্ট নতুন সেগমেন্ট পাচ্ছে না (origin বা প্যাকেজার থেমে আছে), বা CDN পুরনো প্লেলিস্ট ক্যাশ করছেcurl দিয়ে প্লেলিস্ট দুবার, কয়েক সেকেন্ড ব্যবধানে: MEDIA-SEQUENCE বাড়ছে? Age কত?প্লেলিস্টের TTL সেগমেন্টের দৈর্ঘ্যের অর্ধেকের কম; প্যাকেজার দেখুন
লাইভ চালু, স্পিনার, এরর নেই, বাফার ভর্তিপ্লেহেড বাফারের বাইরে (লাইভের মিডিয়া টাইম ০ থেকে শুরু নয়)স্নিপেটে time বনাম bufferedপ্লেহেড বাফারের শুরুতে আনুন (চ্যাপ্টার ১২)
hls.js: bufferStalledErrorবাফার ফুরিয়েছে; বা বাফারে ছোট ফাঁকbuffered-এ একাধিক রেঞ্জ আছে কিনাফাঁক থাকলে প্যাকেজিংয়ে সেগমেন্টের সীমানা মেলান; লাইব্রেরির gap-jump সেটিং
লম্বা সেশনে append ব্যর্থ, QuotaExceededError বা bufferFullErrorপেছনের বাফার কখনো মোছা হয় নাএররের নাম; buffered-এর শুরু অনেক পেছনেপেছনের বাফার সীমিত করুন (hls.js-এ backBufferLength)
কোয়ালিটি নিচেই আটকে থাকেথ্রুপুট মাপ ভুল (ছোট সেগমেন্ট, CORS preflight), প্লেয়ারের আকারের ক্যাপ, Media Capabilities বাদ দিয়েছেস্নিপেটে লেভেল আর estimate kbps; প্লেয়ারের আকারক্যাপ নিয়ম দেখুন; থ্রুপুট মাপে কী ঢুকছে দেখুন
কোয়ালিটি ঘনঘন ওঠানামা করেABR অস্থির, শুধু থ্রুপুটের উপর নির্ভরলেভেল বদলের ইভেন্ট গুনুনওঠার জন্য বাফারের শর্ত; হাইব্রিড ABR (বাফার ও ABR)
উঁচু রেন্ডিশন বেছেছে কিন্তু স্ক্রিনে নিচুটাইবাফারে আগের রেন্ডিশন জমালেভেল বদলের সময় থেকে বাফারের দৈর্ঘ্যস্বাভাবিক; দ্রুত চাইলে সামনের বাফার বদলানো

seek, ক্যাপশন, DRM, আউটপুট

লক্ষণসম্ভাব্য কারণনিশ্চিত হবেন যেভাবেসমাধান
seek বার ভিডিওর শেষ পর্যন্ত যায় না, দৈর্ঘ্য দেখায় নাMSE-তে duration সেট হয়নিস্নিপেটে Infinity আর seekablemediaSource.duration সেট করুন
seek করলে একটু আগে বা পরে গিয়ে পড়েসেগমেন্ট কীফ্রেম দিয়ে শুরু হয় না, বা নেটিভ পথে দ্রুত seek কীফ্রেমে যায়ffprobe -show_frames দিয়ে সেগমেন্টের প্রথম ফ্রেম key_frame=1?প্রতিটা সেগমেন্ট কীফ্রেম দিয়ে শুরু; EXT-X-INDEPENDENT-SEGMENTS
ক্যাপশন দেখায় নাtrack-এর ফাইল আরেক অরিজিনে অথচ video-তে crossorigin নেই; ভুল MIME; ফাইল WEBVTT দিয়ে শুরু নয়; ট্র্যাকের mode disabledস্নিপেটে textTracks; Network-এ .vtt রিকোয়েস্ট আর content-typecrossorigin অ্যাট্রিবিউট আর CORS; text/vtt; mode = 'showing' (ক্যাপশন চ্যাপ্টার)
ক্যাপশন আছে কিন্তু সময় সরে আছেHLS-এ X-TIMESTAMP-MAP নেই বা ভুল, তাই WebVTT-র সময় মিডিয়ার সময়ের সাথে মেলে না.vtt ফাইলের হেডার পড়ুনপ্যাকেজারে টাইমস্ট্যাম্প ম্যাপ ঠিক করুন
DRM: লাইসেন্স রিকোয়েস্টে 403টোকেনের মেয়াদ শেষ, ভুল কনটেন্ট আইডি, ইউজারের অধিকার নেইলাইসেন্স রেসপন্সের বডি পড়ুনটোকেন নতুন করুন; লাইসেন্স সার্ভারের লগ
DRM: লাইসেন্স 200, তবু চলে নানিরাপত্তা স্তর (robustness) কম, ডিভাইস উঁচু রেজোলিউশনের অনুমতি পায় নাrequestMediaKeySystemAccess-এর কনফিগ; কোন রেন্ডিশনে ব্যর্থওই স্তরের জন্য অনুমোদিত রেন্ডিশনে সীমিত করুন
বাইরের মনিটরে বা প্রজেক্টরে কালো স্ক্রিন, ল্যাপটপে ঠিকHDCP সমর্থন নেই এমন কেবল বা মনিটর; DRM নীতি আউটপুট আটকায়শুধু DRM কনটেন্টে হয় কিনা; অন্য কেবলে চেষ্টাইউজারকে স্পষ্ট বার্তা; নীতি অনুযায়ী নিচু রেজোলিউশন
স্ক্রিন রেকর্ডিং বা স্ক্রিনশেয়ারে ভিডিও কালোDRM-এর স্বাভাবিক সুরক্ষাএকই কনটেন্ট DRM ছাড়া রেকর্ড হয় কিনাএটা বাগ নয়; সাপোর্টের উত্তর তৈরি রাখুন

শুধু কিছু জায়গায়

লক্ষণসম্ভাব্য কারণনিশ্চিত হবেন যেভাবেসমাধান
Chrome-এ চলে, Safari-তে নানেটিভ HLS পথ (Safari) কঠোর: কোডেক স্ট্রিং, টার্গেট ডিউরেশন, ক্যাপশন ফরম্যাটSafari Web Inspector-এর কনসোল; mediastreamvalidatorApple-এর HLS নিয়ম মেনে প্যাকেজ
Safari-তে চলে, Chrome আপডেটের পর অদ্ভুত আচরণChrome এখন নেটিভ HLS চালায়, আপনার কোড নেটিভ পথ বেছে নিচ্ছেস্নিপেটে mse: falseMSE আগে, নেটিভ পরে
ডেস্কটপে চলে, iOS-এ নাplaysinline নেই, অটোপ্লে নীতি, MSE নেই, কম মেমরিআসল iPhone USB দিয়ে Web Inspector-এউপরের iOS সারিগুলো
শুধু একটা TV ব্র্যান্ডে ক্র্যাশ বা বিকৃত ছবিকম মেমরি, ছোট MSE কোটা, পুরনো ব্রাউজার ইঞ্জিন, কোডেক লেভেলের সীমাওই TV-র রিমোট ডিবাগিং বা লগ; ডিভাইস ধরে QoEবাফার গোল কমান, ছোট রেন্ডিশন, ওই মডেলের জন্য আলাদা কনফিগ
incognito-তে চলে, সাধারণ উইন্ডোতে নাএক্সটেনশন (অ্যাড ব্লকার সেগমেন্ট বা লাইসেন্স URL আটকায়), পুরনো ক্যাশ, সার্ভিস ওয়ার্কারএক্সটেনশন বন্ধ করে; Application প্যানেলে সার্ভিস ওয়ার্কারURL প্যাটার্ন বদলান; সার্ভিস ওয়ার্কার আপডেট
SPA-তে কয়েকটা ভিডিও দেখার পর ট্যাব ধীর বা ক্র্যাশপুরনো প্লেয়ার ধ্বংস হয় নাDevTools Memory; Media প্যানেলে মৃত প্লেয়ার জমছেরাউট বদলে hls.destroy() বা player.destroy()

একটা ভালো বাগ রিপোর্টে কী থাকে

“ভিডিও চলে না” দিয়ে কিছু করা যায় না। সাপোর্ট টিম আর ইউজারের জন্য একটা ছোট ফর্ম রাখুন, আর প্রতিটা অভিযোগে এই জিনিসগুলো চান:

  1. পেজের URL আর ভিডিওর আইডি।
  2. ডিভাইস, OS ভার্সন, ব্রাউজার আর তার ভার্সন (Chrome-এ chrome://version)।
  3. ঠিক কখন (সময় অঞ্চলসহ), যাতে লগ খোঁজা যায়।
  4. প্লেয়ারের সেশন আইডি (sid), যা QoE বিকন আর CDN লগ দুটোতেই আছে (চ্যাপ্টার ১১)। প্লেয়ারের এরর স্ক্রিনে এটা দেখালে ইউজার সহজে কপি করতে পারে।
  5. উপরের কনসোল স্নিপেটের আউটপুট।
  6. সম্ভব হলে DevTools Media প্যানেলের JSON এক্সপোর্ট, বা Network প্যানেলের HAR ফাইল।

প্লেয়ারের এরর স্ক্রিনে একটা ছোট কোড দেখান, শুধু “কিছু একটা ভুল হয়েছে” নয়। যেমন E-NET-403 · 45f4227c: প্রথম অংশ কোন লেয়ার আর কোন এরর, দ্বিতীয় অংশ সেশন আইডির শুরু। ইউজারের কাছে এটা অর্থহীন নয়, সাপোর্টে পাঠানোর মতো একটা জিনিস। আর আপনার কাছে এটা লগের সরাসরি ঠিকানা। ইউজারের জন্য বার্তাটা সাধারণ ভাষায় রাখুন (“ভিডিওটা এই মুহূর্তে চালানো যাচ্ছে না, একটু পরে আবার চেষ্টা করুন”), কোডটা নিচে ছোট করে।

ইনসিডেন্টের সময় অভ্যাস

  • আগে পরিধি, তারপর কারণ। QoE ড্যাশবোর্ডে দেখুন: সব ইউজার, নাকি একটা দেশ, একটা CDN, একটা ব্রাউজার ভার্সন, একটা প্লেয়ার রিলিজ? পরিধিই অর্ধেক উত্তর দেয়।
  • শেষ কী বদলেছে? প্লেয়ার রিলিজ, প্যাকেজার কনফিগ, CDN নিয়ম, DRM কী, ব্রাউজারের নতুন ভার্সন। Chrome-এর নেটিভ HLS-এর মতো ঘটনা দেখায় যে “আমরা কিছু বদলাইনি” মানে “কিছুই বদলায়নি” নয়।
  • একবারে একটা পরিবর্তন। দুটো একসাথে বদলালে কোনটা কাজ করল জানবেন না।
  • লাইব্রেরির ডিবাগ লগ চালু করা যায় এমন একটা গোপন সুইচ রাখুন, যেমন URL-এ ?playerdebug=1, যাতে প্রোডাকশনে ইউজারের ডিভাইসেই লগ দেখা যায়।
  • ঠিক হওয়ার পর একটা পরীক্ষা যোগ করুন। এই চ্যাপ্টারের duration: Infinity বাগটার মতো প্রতিটা ঠিক করা সমস্যা পরের বার একটা স্বয়ংক্রিয় চেক হয়ে ফিরুক।

মূল শিক্ষা

  1. প্রথম প্রশ্ন সবসময়: কোন প্লেব্যাক পথ? currentSrc-এ blob: মানে MSE, mediaKeys মানে DRM, বাকিটা নেটিভ।
  2. Chrome এখন HLS নেটিভ চালায়; MSE আগে, নেটিভ পরে, নইলে লাইব্রেরি আর অ্যানালিটিক্স চুপচাপ বাদ পড়ে।
  3. লাইনের শুরু থেকে শেষ: নেটওয়ার্ক ও CORS, ম্যানিফেস্ট, কোডেক ও append, DRM, বাফার ও ABR, রেন্ডারিং, ডিভাইস। যে লেয়ারের আগে ঠিক আর পরে ভুল, সমস্যা সেখানে।
  4. curl-এ চলে, ব্রাউজারে না = প্রায় সবসময় CORS।
  5. frames বাড়ছে কিনা দেখে ডিকোডের সমস্যা আর আউটপুটের সমস্যা আলাদা করুন।
  6. buffered বনাম currentTime লাইভের অর্ধেক “অনন্ত স্পিনার” ব্যাখ্যা করে।
  7. লাইসেন্স সার্ভারের এররের বডি পড়ুন; DRM-এর আসল কারণ ওখানেই।
  8. এরর স্ক্রিনে কোড আর সেশন আইডি দেখান, যাতে প্রতিটা অভিযোগ লগের ঠিকানা হয়ে আসে।
  9. প্রতিটা ঠিক করা বাগ একটা পরীক্ষা হয়ে ফিরুক।