ভিডিও মাস্টারি — পর্ব ৩: প্রোডাকশন-গ্রেড ট্রান্সকোডার
দশজন থেকে দশ হাজার — আর্কিটেকচার, স্টেট মেশিন, চাংকড এনকোডিং, পার-টাইটেল ল্যাডার, প্যাকেজিং, CDN, খরচ, আর ব্যর্থতার পূর্ণ তালিকা।
দশজন থেকে দশ হাজার — আর্কিটেকচার, স্টেট মেশিন, চাংকড এনকোডিং, পার-টাইটেল ল্যাডার, প্যাকেজিং, CDN, খরচ, আর ব্যর্থতার পূর্ণ তালিকা।
যে দিনটায় সব ভেঙে পড়ল
আল-বিরুনির কোর্স প্ল্যাটফর্ম ছয় মাস ধরে ঠিকঠাক চলছে। পর্ব ২-এর ওয়ার্কারটা চুপচাপ কাজ করে যাচ্ছে।
তারপর একটা কোর্স ভাইরাল হলো। এক সপ্তাহে ৪০ জন নতুন শিক্ষক যোগ দিল, আর প্রথম দিনেই ৩০০টা ভিডিও আপলোড হলো।
যা যা হলো, ক্রমানুসারে:
- সারিতে ৩০০টা কাজ জমল, একটা একটা করে চলছে। শেষ কাজটার অপেক্ষা: প্রায় তিন দিন।
- ডিস্ক ভরে গেল। ffmpeg মাঝপথে মরল, আর অর্ধেক লেখা টুকরোগুলো ফোল্ডারে পড়ে রইল।
- অর্ধেক-প্রসেস হওয়া ভিডিওগুলো ওয়েবসাইটে “রেডি” দেখাচ্ছে, কারণ ফোল্ডার তো আছে — কিন্তু চালালে মাঝপথে শেষ হয়ে যায়।
- এনকোডিং সব সিপিইউ খেয়ে ফেলল, ফলে যারা পুরনো ভিডিও দেখছিল তাদেরও বাফারিং শুরু হলো।
- একটা ডিপ্লয় হলো। মেমোরির সারি মুছে গেল। কোন কাজ কতদূর হয়েছিল, কেউ জানে না।
- একজন শিক্ষক একই ভিডিও তিনবার আপলোড করল, কারণ সে ভাবল কাজ হচ্ছে না। সিস্টেম তিনবার এনকোড করল।
আল-বিরুনি বুঝল, তার কোড খারাপ না। তার আকৃতিটা ভুল।
এই পর্বটা ওই আকৃতি নিয়ে।
১. মূল ধারণা: প্রতিটা ধাপ আলাদা করো
শেখার ট্রান্সকোডারে সবকিছু এক জায়গায় — আপলোড নেওয়া, সারি রাখা, এনকোড করা, ফাইল রাখা, ফাইল সার্ভ করা। প্রোডাকশনে এই পাঁচটা আলাদা জিনিস, কারণ এদের চাহিদা সম্পূর্ণ আলাদা।
কেন এই ভাগগুলো:
- আপলোড সরাসরি অবজেক্ট স্টোরেজে যাক, তোমার সার্ভারের ভেতর দিয়ে না। ২ গিগার ফাইল অ্যাপ সার্ভারের মধ্য দিয়ে গেলে সে ওই সময়টা আর কিছু করতে পারে না।
- সারি থাকুক এমন জায়গায় যেটা রিস্টার্টে মরে না।
- ওয়ার্কার আলাদা মেশিন — কাজ বাড়লে সংখ্যা বাড়াও, কমলে কমাও।
- ডেলিভারি CDN-এর কাজ। যে মেশিন এনকোড করে, সে যেন দর্শকের সাথে কথা না বলে।
- ডেটাবেস সত্যের একমাত্র উৎস। ফাইল সিস্টেম না।
এই একটা ভাগাভাগিই আল-বিরুনির ছয়টা সমস্যার চারটা মিটিয়ে দেয়।
২. আপলোড: সার্ভারকে মাঝখান থেকে সরাও
ব্রাউজার সরাসরি অবজেক্ট স্টোরেজে (S3 বা সমতুল্য) ফাইল পাঠাক। তোমার সার্ভার শুধু একটা সীমিত সময়ের অনুমতিপত্র বানিয়ে দেয়:
POST /api/uploads
→ { key: "raw/2026/07/abc123.mp4",
url: "https://…?X-Amz-Expires=900&…",
maxBytes: 10737418240 } অনুমতিপত্রে যা যা বাঁধা থাকা দরকার: কোথায় লিখবে (নির্দিষ্ট কী), কতক্ষণের মধ্যে, সর্বোচ্চ কত বড়, আর কোন কনটেন্ট টাইপ। এই চারটা না বাঁধলে কেউ তোমার বাকেটকে ফ্রি স্টোরেজ বানিয়ে ফেলবে।
বড় ফাইলের জন্য মাল্টিপার্ট আপলোড — ফাইলটা কয়েক মেগাবাইটের অংশে ভাগ হয়ে যায়, নেট কেটে গেলে শুধু ওই অংশটা আবার যায়, পুরোটা না। মোবাইল থেকে ২ গিগার ফাইল আপলোডে এটা বাধ্যতামূলক।
আপলোড শেষ হলে স্টোরেজ একটা ঘটনা পাঠায়, সেখান থেকে কাজ শুরু।
ডিডুপ্লিকেশন — একই ফাইল দুবার এলে
আপলোডের সময় ব্রাউজারে ফাইলের একটা হ্যাশ বের করে নাও, বা সার্ভারে আপলোডের পর। ওই হ্যাশ আগে থেকে থাকলে নতুন করে এনকোড করার দরকার নেই — পুরনো আউটপুটটাই নতুন ভিডিওর সাথে জুড়ে দাও।
আল-বিরুনির সেই শিক্ষক তিনবার আপলোড করেছিল — হ্যাশ থাকলে দুবারের কাজ বেঁচে যেত।
৩. probe আর ইনগেস্ট নীতি
probe না করে সারিতে দিও না। ইনপুট নিয়ে অনুমান করা সবচেয়ে বড় ভুল। বাস্তব জীবনে যা আসে:
- ঘোরানো ফোনের ভিডিও, যার আসল মাপ উল্টো
- অডিও নেই এমন ভিডিও (স্ক্রিন রেকর্ডিং)
- ভিডিও নেই, শুধু অডিও (কেউ পডকাস্ট দিয়েছে)
- ৯০ ঘণ্টার ভিডিও (কেউ ভুল ফাইল দিয়েছে)
- ভাঙা ফাইল, যার শেষ অংশ নেই
- ভেরিয়েবল ফ্রেমরেট
- HDR ভিডিও, যেটা সাধারণভাবে ট্রান্সকোড করলে ধূসর হয়ে যায়
- ১০ ফ্রেমের ভিডিও (কেউ ভুল করে চাপ দিয়েছে)
- ৪০টা অডিও ট্র্যাকওয়ালা ফাইল
- এমন কোডেক যেটা তোমার ffmpeg বিল্ডে নেই
তাই একটা স্পষ্ট ইনগেস্ট নীতি লেখো — কী গ্রহণ করবে, কী ফিরিয়ে দেবে, আর কী নিয়ে বিশেষ ব্যবস্থা নেবে:
গ্রহণ : ভিডিও স্ট্রিম আছে, দৈর্ঘ্য ১ সেকেন্ড–৬ ঘণ্টা, ফাইল ২০ GB-র নিচে
বিশেষ ব্যবস্থা : HDR (টোন ম্যাপ), VFR (নির্দিষ্ট করা), ঘোরানো (ঠিক করা), অডিও নেই (নীরব ট্র্যাক)
ফিরিয়ে দাও : ভিডিও নেই, ফাইল ভাঙা, অচেনা কোডেক, সীমার বাইরে দৈর্ঘ্য গুরুত্বপূর্ণ কথা: ফিরিয়ে দিলে ব্যবহারকারীকে বোধগম্য ভাষায় বলো। “job failed” না — “এই ফাইলে কোনো ভিডিও পাওয়া যায়নি, সম্ভবত এটা অডিও ফাইল”। সাপোর্টের অর্ধেক কাজ এখানেই কমে যায়।
৪. কাজের মডেল আর স্টেট মেশিন
এবার সবচেয়ে গুরুত্বপূর্ণ অংশ — কাজের অবস্থা।
স্টেট মেশিন
নিয়মগুলো:
- অবস্থা বদলায় শুধু ডেটাবেসে, আর সেটাই সত্য।
- দর্শকের কাছে ভিডিও দেখাবে শুধু
readyহলে। - প্রতিটা বদলের সাথে সময় লিখে রাখো — পরে “কোন ধাপে কত সময় লাগে” জানার জন্য এটাই একমাত্র উৎস।
একটা সরল টেবিল:
create table jobs (
id text primary key,
video_id text not null,
input_key text not null,
content_hash text, -- ডিডুপের জন্য
status text not null, -- উপরের অবস্থাগুলো
attempts int not null default 0,
lease_until timestamptz, -- ওয়ার্কারের দখলের মেয়াদ
worker_id text,
progress int not null default 0,
probe jsonb, -- probe-এর ফল
ladder jsonb, -- কোন ধাপগুলো বানানো হবে
error text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
create index on jobs (status, created_at);
create unique index on jobs (content_hash) where content_hash is not null; আইডেম্পোটেন্সি
ঘটনা-ভিত্তিক সিস্টেমে একই বার্তা দুবার আসা স্বাভাবিক ঘটনা, ব্যতিক্রম না। ধরে নাও আসবেই।
তাই প্রতিটা কাজের একটা নির্ধারক চাবি থাকুক — যেমন ফাইলের হ্যাশ + ল্যাডারের সংস্করণ:
job_key = sha256(content_hash + ":" + ladder_version) ওই চাবি আগে থেকে থাকলে নতুন কাজ না বানিয়ে পুরনোটার ফল ফিরিয়ে দাও। এতে দুবার এনকোড হয় না, আর একই আউটপুট দুই জায়গা থেকে লেখার দৌড়ও হয় না।
ladder_version কেন? কারণ ছয় মাস পর তুমি ল্যাডার বদলাবে, আর তখন ইচ্ছা করেই আবার এনকোড করতে চাইবে। সংস্করণ নম্বরটা সেটাকে স্পষ্ট করে রাখে।
দখল আর হার্টবিট
ওয়ার্কার কাজ নেওয়ার সময় একটা মেয়াদসহ দখল নিক:
update jobs
set status = 'encoding',
worker_id = $1,
lease_until = now() + interval '5 minutes',
attempts = attempts + 1
where id = (
select id from jobs
where status = 'queued'
or (status = 'encoding' and lease_until < now()) -- মৃত ওয়ার্কারের কাজ ফেরত
order by created_at
for update skip locked
limit 1
)
returning *; চলাকালীন ওয়ার্কার প্রতি মিনিটে দখলের মেয়াদ বাড়াক (হার্টবিট)। ওয়ার্কার মরে গেলে মেয়াদ শেষ হবে, আর কাজটা নিজে থেকে ফিরে আসবে।
“চিরকাল প্রসেসিং” অবস্থাটা এভাবেই দূর হয় — আল-বিরুনির দ্বিতীয় সমস্যা।
for update skip locked লাইনটা ছোট কিন্তু গুরুত্বপূর্ণ: এটা নিশ্চিত করে যে দশটা ওয়ার্কার একসাথে একই কাজ তুলে নেবে না।
রিট্রাই, কিন্তু বুদ্ধি করে
সব ব্যর্থতা এক রকম না:
| ধরন | উদাহরণ | কী করবে |
|---|---|---|
| ক্ষণস্থায়ী | স্টোরেজে সাময়িক সমস্যা, ওয়ার্কার মরে গেছে | আবার চেষ্টা, ধাপে ধাপে বেশি অপেক্ষা করে |
| স্থায়ী | ফাইল ভাঙা, ভিডিও স্ট্রিম নেই | সাথে সাথে থামো, ব্যবহারকারীকে জানাও |
| সম্পদের অভাব | ডিস্ক ভরা, মেমোরি শেষ | অন্য ওয়ার্কারে দাও, সাথে অ্যালার্ট |
তিনবার চেষ্টার পরও না হলে কাজটাকে dead করে আলাদা তালিকায় রাখো, আর মানুষকে জানাও। ব্যর্থ কাজ চুপচাপ হারিয়ে যাওয়া সবচেয়ে খারাপ পরিণতি — কারণ তখন কেউ জানেই না যে একটা ভিডিও কখনো প্রকাশিত হয়নি।
৫. কাজের ধাপগুলো: একটা DAG
একটা ভিডিও “রেডি” হতে যা যা লাগে, সেগুলো আসলে একটা নির্ভরতার গ্রাফ:
এভাবে ভাঙার সুবিধা:
- প্রতিটা ধাপ আলাদা করে আবার চেষ্টা করা যায় (থাম্বনেইল ব্যর্থ হলে পুরো এনকোড আবার করতে হয় না)
- সমান্তরালে চালানো যায়
- কোন ধাপে কত সময় লাগছে আলাদা করে মাপা যায়
ছোট সিস্টেমে এটা একটা টেবিল আর কয়েকটা স্ট্যাটাস দিয়েই করা যায়; বড় হলে ওয়ার্কফ্লো ইঞ্জিন ব্যবহার করা হয়। আগে টেবিল দিয়ে শুরু করো — বেশিরভাগ প্ল্যাটফর্মের জন্য সেটাই যথেষ্ট।
৬. চাংকড ট্রান্সকোডিং — সবচেয়ে কার্যকর কৌশল
দুই ঘণ্টার একটা ভিডিও এক মেশিনে এনকোড করতে ৯০ মিনিট লাগে। কোর বাড়ালে কিছুটা কমে, কিন্তু একটা সীমার পর আর কমে না — কারণ এনকোডিং ধারাবাহিক কাজ, প্রতিটা ফ্রেম আগেরটার উপর নির্ভর করে।
কিন্তু ভিডিও তো ভাগ করা যায়:
১. কেটে নাও (এনকোড না করে, শুধু কপি):
ffmpeg -i input.mp4 -c copy -map 0 \
-f segment -segment_time 60 -reset_timestamps 1 \
-segment_list chunks.csv \
chunks/part-%04d.mp4 -c copy মানে ডিকোড-এনকোড কিছুই হচ্ছে না, শুধু কেটে আলাদা ফাইল বানানো হচ্ছে। দুই ঘণ্টার ভিডিও কাটতে কয়েক সেকেন্ড লাগে।
২. প্রতিটা টুকরোকে আলাদা কাজ হিসেবে সারিতে দাও।
৩. ২০টা ওয়ার্কার সমান্তরালে চালাক।
৪. জোড়া দাও (আবার, এনকোড ছাড়া):
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4 ৯০ মিনিটের কাজ নেমে আসে ৫–৭ মিনিটে।
শর্তগুলো — না মানলে ফল ভয়ংকর
ক. কাটাকাটি হতে হবে কি-ফ্রেমের ঠিক সীমানায়। না হলে টুকরোর শুরুতে ভাঙা ফ্রেম থাকবে। ইনপুটে কি-ফ্রেম অনিয়মিত হলে আগে একটা দ্রুত “নর্মালাইজ” পাস চালাতে হয় — নির্দিষ্ট ছন্দে কি-ফ্রেমসহ একটা মধ্যবর্তী ফাইল বানানো।
খ. সব টুকরো একদম একই সেটিংসে এনকোড হতে হবে। একই CRF, একই preset, একই প্রোফাইল, এমনকি একই ffmpeg সংস্করণ। ওয়ার্কারদের মধ্যে সংস্করণ আলাদা হলে জোড়ার জায়গায় সূক্ষ্ম পার্থক্য দেখা যাবে। তাই ওয়ার্কারের ইমেজে ffmpeg-এর সংস্করণ পিন করে রাখা বাধ্যতামূলক।
গ. রেট কন্ট্রোল টুকরোভেদে আলাদা আচরণ করে। প্রতিটা টুকরো আলাদাভাবে “শুরু” করে, তাই টুকরোর সীমানায় কোয়ালিটি সামান্য লাফ দিতে পারে। সমাধান — টুকরোগুলো যথেষ্ট বড় রাখা (৩০–৬০ সেকেন্ড), আর সীমানার আগে-পরে সামান্য ওভারল্যাপ রেখে পরে ফেলে দেওয়া।
ঘ. অডিও আলাদা করে, একবারে এনকোড করো। অডিও এমনিতেই হালকা, আর টুকরো করে এনকোড করলে জোড়ার জায়গায় ক্লিক শোনা যায়। পুরো অডিও একটা কাজ হিসেবে চালাও।
এই কারণেই পর্ব ২-এর সেই -g আর -force_key_frames লাইনগুলো এত গুরুত্বপূর্ণ ছিল। কি-ফ্রেম নিয়ন্ত্রণে না থাকলে চাংকিং করাই যায় না।
৭. ল্যাডার: স্থির থেকে পার-টাইটেল
স্থির ল্যাডার (সবসময় 240/360/480/720/1080) দিয়ে শুরু করা ঠিক আছে। কিন্তু দুটো ভিডিওর চাহিদা কখনোই এক না:
- স্লাইড দেখানো লেকচার — 1080p-তেও ১ Mbps যথেষ্ট
- হাতে ধরা ক্যামেরায় ভিড়ের ভিডিও — 720p-তেও ৪ Mbps কম পড়ে
ধাপ ১: বিভাগ অনুযায়ী প্রিসেট
সবচেয়ে সহজ উন্নতি — কনটেন্টের ধরন অনুযায়ী আলাদা প্রিসেট:
screencast / slides → কম বিটরেট, বেশি রেজলিউশন (লেখা পড়তে হবে)
talking head → মাঝারি সব
sports / action → বেশি বিটরেট, দরকার হলে কম রেজলিউশন
animation → খুব কম বিটরেটেই ভালো আসে শিক্ষক আপলোডের সময় ধরন বেছে দিলেই ২০% সাশ্রয় সম্ভব, কোনো জটিল হিসাব ছাড়াই।
ধাপ ২: পার-টাইটেল এনকোডিং
প্রতিটা ভিডিওর জন্য আলাদা করে ধাপ ঠিক করা। ব্যবহারিক রূপটা এরকম:
- ভিডিও থেকে কয়েকটা প্রতিনিধিত্বমূলক অংশ নাও (শুরু, মাঝ, শেষের ১০ সেকেন্ড করে)।
- সেগুলোকে কয়েকটা বিটরেটে এনকোড করো।
- প্রতিটার VMAF মাপো।
- যে বিন্দুর পর বিটরেট বাড়ালেও VMAF আর বাড়ছে না, সেটাই ওই রেজলিউশনের সঠিক বিটরেট।
- প্রতিটা রেজলিউশনের জন্য এভাবে বিন্দু বের করে ল্যাডার বানাও।
ফল: গড়ে ২০–৩০% ব্যান্ডউইথ সাশ্রয়, একই দৃশ্যমান মানে। বড় প্ল্যাটফর্মে এটা মাসে বড় অঙ্কের টাকা।
খরচ: নমুনা এনকোডিং আর VMAF মাপার জন্য বাড়তি কম্পিউট। তাই এটা সাধারণত শুধু জনপ্রিয় ভিডিওর জন্য চালানো হয় — বাকিরা স্থির ল্যাডারেই থাকে।
ধাপ ৩: রেজলিউশনের সীমা মানা
একটা নিয়ম যেটা প্রায়ই ভুলে যাওয়া হয়: প্রতিটা বিটরেটের একটা “সঠিক” রেজলিউশন আছে। ৩০০ Kbps-এ 720p পাঠানোর মানে হলো — বড় ক্যানভাসে সব ব্লক ভেসে উঠবে। ওই বিটরেটে 240p অনেক পরিষ্কার দেখাবে।
তাই ল্যাডারে বিটরেট আর রেজলিউশন একসাথে নামে, আলাদা করে না।
৮. এনকোডিং কোথায় চলবে
সফটওয়্যার বনাম হার্ডওয়্যার
| সফটওয়্যার (x264, SVT-AV1) | হার্ডওয়্যার (NVENC, QSV) | |
|---|---|---|
| গতি | ধীর | ১০–২০ গুণ দ্রুত |
| একই মানে ফাইল সাইজ | ছোট | ~২০–৩০% বড় |
| খরচ | সাধারণ সিপিইউ, সস্তা | জিপিইউ মেশিন, দামি |
| নমনীয়তা | সব নব হাতে | সীমিত অপশন |
| কখন ভালো | যে ভিডিও বহুবার দেখা হবে | লাইভ, বা দ্রুত দিতে হবে এমন কিছু |
হিসাবটা সোজা: একটা ভিডিও লাখবার দেখা হলে ধীরে ভালো করে এনকোড করার খরচ একবারের, কিন্তু ব্যান্ডউইথের সাশ্রয় প্রতিবারের। উল্টোদিকে, যে ভিডিও দশজন দেখবে, তার পেছনে জিপিইউ সময় নষ্ট করার মানে নেই।
দুই ধাপের কৌশল
অনেক প্ল্যাটফর্ম দুটোই করে:
- আপলোডের সাথে সাথে দ্রুত একটা ৭২০p বের করে দেয় (হার্ডওয়্যার বা
veryfast) — ভিডিও ২ মিনিটেই দেখার উপযোগী। - পেছনে ধীরে ধীরে পূর্ণ ল্যাডার বানায়, তারপর চুপচাপ বদলে দেয়।
ব্যবহারকারীর কাছে সিস্টেমটা দ্রুত মনে হয়, অথচ শেষ ফল ভালো থাকে।
অটোস্কেলিং
ওয়ার্কারের সংখ্যা সারির গভীরতা দেখে বাড়াও-কমাও, সিপিইউ ব্যবহার দেখে না। কারণ এনকোডিংয়ে সিপিইউ সবসময়ই ১০০% — ওটা কোনো তথ্য দেয় না।
সারিতে অপেক্ষমাণ কাজ > ২০ → ওয়ার্কার বাড়াও
৫ মিনিট ধরে সারি খালি → ওয়ার্কার কমাও (তবে শূন্যে না)
সবচেয়ে পুরনো কাজের বয়স > ১৫ মিনিট → অ্যালার্ট ট্রান্সকোডিং স্পট/প্রিএম্পটিবল মেশিনের জন্য আদর্শ কাজ — বাধাগ্রস্ত হলে কেবল ওই টুকরোটা আবার চালালেই হয়। খরচ ৬০-৮০% পর্যন্ত কমতে পারে। শর্ত: দখলের মেয়াদ আর রিট্রাই ঠিকমতো কাজ করতে হবে, যেটা আমরা ইতিমধ্যে বানিয়েছি।
৯. প্যাকেজিং: এনকোডিং থেকে আলাদা রাখো
এনকোডার মান তৈরি করে; প্যাকেজার ঠিক করে সেটা কীভাবে বিলি হবে — সেগমেন্টের দৈর্ঘ্য, ম্যানিফেস্ট, এনক্রিপশন।
দুটো আলাদা রাখলে যা যা সহজ হয়:
- প্রোটোকল যোগ করা (HLS-এর পাশে DASH) — আবার এনকোড করতে হয় না
- সেগমেন্টের দৈর্ঘ্য বদলানো
- DRM যোগ করা
- নতুন ধরনের ম্যানিফেস্ট বানানো
CMAF-এর কারণে একই fMP4 সেগমেন্ট দুই প্রোটোকলেই চলে, শুধু ম্যানিফেস্ট দুটো:
media/
video/720p/ init.mp4 seg-0001.m4s seg-0002.m4s ...
audio/bn/ init.mp4 seg-0001.m4s ...
subs/bn.vtt
manifests/
master.m3u8 ← HLS
manifest.mpd ← DASH এক সেট মিডিয়া ফাইল, দুই সেট ম্যানিফেস্ট। স্টোরেজ আর CDN খরচ অর্ধেক।
DRM আর অ্যাক্সেস
তিন স্তরের সুরক্ষা, কনটেন্ট অনুযায়ী বাছো:
| স্তর | কী করে | কখন |
|---|---|---|
| সইসহ URL | নির্দিষ্ট সময় পর লিংক অচল | বেশিরভাগ ক্ষেত্রে যথেষ্ট |
| AES এনক্রিপশন | সেগমেন্ট এনক্রিপ্টেড, চাবি আলাদা সার্ভারে | কোর্স, পেইড কনটেন্ট |
| DRM (Widevine/FairPlay/PlayReady) | চাবি ডিভাইসের সুরক্ষিত অংশে | স্টুডিও কনটেন্ট, চুক্তিতে বাধ্যতামূলক |
বেশিরভাগ প্ল্যাটফর্ম প্রথম স্তরেই শুরু করতে পারে। DRM-এ যাওয়ার আগে নিশ্চিত হও যে সেটা সত্যিই দরকার — খরচ আর জটিলতা দুটোই বড়।
১০. স্টোরেজ আর ডেলিভারি
স্টোরেজের হিসাব
একটা ১ ঘণ্টার 1080p ভিডিও:
কাঁচা আপলোড ~২.৫ GB
240p ~০.১৩ GB
360p ~০.৩০ GB
480p ~০.৬০ GB
720p ~১.৩০ GB
1080p ~২.৬০ GB
থাম্বনেইল, স্প্রাইট, সাব ~০.০২ GB
মোট ~৭.৫ GB প্রতি ঘণ্টার ভিডিওর জন্য প্রায় ৭ গুণ জায়গা। ১০,০০০ ঘণ্টা মানে ৭৫ টেরাবাইট।
সিদ্ধান্তগুলো যেখানে টাকা লুকিয়ে
কাঁচা ফাইলটা রাখবে? রাখলে পরে নতুন কোডেকে আবার এনকোড করা যায়, ভুল ধরা পড়লে ঠিক করা যায়। না রাখলে জায়গা বাঁচে কিন্তু ভবিষ্যতের দরজা বন্ধ। বেশিরভাগ টিম রাখে — তবে ৩০ দিন পর সস্তা “ঠান্ডা” স্টোরেজে সরিয়ে দেয়।
কেউ দেখে না এমন ভিডিও। অনেক প্ল্যাটফর্মে অর্ধেক ভিডিও কার্যত কেউ দেখে না। কৌশল: শুধু একটা মাঝারি ধাপ আগে বানিয়ে রাখো, বাকিগুলো প্রথম দর্শক এলে বানাও (কয়েক সেকেন্ড দেরি হবে, একবার)। খরচ নাটকীয়ভাবে কমে।
পুরনো ভিডিওর উপরের ধাপ মুছে ফেলা। দুই বছরের পুরনো ভিডিওর 1080p ধাপ হয়তো মাসে দুবার চাওয়া হয়। মুছে দিয়ে দরকার হলে আবার বানানো যায়।
CDN
ভিডিওর টুকরো একদম আদর্শ ক্যাশ-উপযোগী জিনিস: বদলায় না, বড়, বারবার চাওয়া হয়।
- লম্বা ক্যাশ সময় দাও (এক বছর), আর ফাইলের পথে সংস্করণ রাখো যাতে বদলালে পথ বদলে যায়।
- ম্যানিফেস্টে ছোট ক্যাশ সময় — বিশেষ করে লাইভে, যেখানে তালিকা বারবার বদলায়।
- অরিজিন শিল্ড — CDN-এর অনেক দিক থেকে একসাথে মূল স্টোরেজে চাপ আসা ঠেকায়।
- ক্যাশ কী সরল রাখো — অপ্রয়োজনীয় কোয়েরি প্যারামিটার ক্যাশ ভেঙে দেয়। একই ফাইল যদি ভিন্ন ভিন্ন টোকেনসহ চাওয়া হয়, আর টোকেনটা ক্যাশ কী-তে থাকে, তাহলে ক্যাশ কখনো গরম হবে না। এই একটা ভুল CDN-এর পুরো উপকার নষ্ট করে দেয়।
১১. দৃশ্যমানতা: কী মাপবে
দুই ধরনের সংখ্যা দরকার।
ভেতরের
| মাপ | কেন |
|---|---|
| সারির গভীরতা | সবচেয়ে আগেভাগে সতর্ক করা সংকেত |
| সবচেয়ে পুরনো কাজের বয়স | গভীরতার চেয়েও ভালো — ২০টা কাজ ঠিক আছে, ২০ মিনিট অপেক্ষা না |
| এনকোডিং গতি (realtime-এর কত গুণ) | ক্ষমতার পরিকল্পনার ভিত্তি |
| ব্যর্থতার হার, কারণ অনুযায়ী ভাগ করা | কোন ধরনের ইনপুট ভাঙছে |
| প্রতি ধাপে সময় (probe/encode/package) | কোথায় সময় যাচ্ছে |
| প্রতি ঘণ্টা ভিডিওতে খরচ | সিদ্ধান্তের একমাত্র সৎ মাপকাঠি |
দর্শকের দিকের
পর্ব ১-এর সেই তালিকা — স্টার্টআপ টাইম, রিবাফার রেশিও, গড় বিটরেট, প্লে ফেইলিওর, ধাপ বদলের হার।
দ্বিতীয় তালিকাটা প্রথমটার চেয়ে বেশি গুরুত্বপূর্ণ। তোমার সব কাজ সবুজ দেখাতে পারে, অথচ ল্যাডারের নিচের ধাপটা ভারী বলে গ্রামের দর্শকরা বাফার করেই যাচ্ছে। ওই সত্যটা শুধু দর্শকের দিকের সংখ্যাতেই ধরা পড়ে।
আর ভাগ করে দেখো — দেশ অনুযায়ী, ডিভাইস অনুযায়ী, নেটওয়ার্ক অনুযায়ী। গড় সংখ্যা প্রায়ই মিথ্যা বলে: সামগ্রিক রিবাফার ০.৩% হতে পারে, অথচ একটা নির্দিষ্ট অঞ্চলে ৮%।
SLO ঠিক করো
৯৫% ভিডিও আপলোডের ৩০ মিনিটের মধ্যে দেখার উপযোগী
৯৯% কাজ তিনবার চেষ্টার মধ্যে সফল
স্টার্টআপ টাইম (p75) ১.৫ সেকেন্ডের নিচে
রিবাফার রেশিও (p95) ১%-এর নিচে সংখ্যা ঠিক করা মানে সিদ্ধান্তের ভিত্তি তৈরি করা — না হলে “আরও দ্রুত করা দরকার” নিয়ে অন্তহীন তর্ক চলে।
১২. ব্যর্থতার তালিকা — বাস্তব অভিজ্ঞতা
প্রতিটাই কারো না কারো রাত জাগার কারণ হয়েছে।
১. অডিও ধীরে ধীরে সরে যায়। লক্ষণ: শুরুতে ঠিক, ৪০ মিনিট পর ঠোঁট আর শব্দ আলাদা। কারণ: ভেরিয়েবল ফ্রেমরেট। সমাধান: -vsync cfr -r N।
২. ধাপ বদলানোর সময় ছবি আটকায় বা কালো ঝিলিক। কারণ: ধাপে ধাপে কি-ফ্রেম আলাদা জায়গায়। সমাধান: -g, -keyint_min, -sc_threshold 0, দরকার হলে -force_key_frames।
৩. আইফোনে শুধু শব্দ, ছবি কালো। কারণ: pixel format 4:2:0 না, বা প্রোফাইল/লেভেল ডিভাইসের সীমার বাইরে। সমাধান: -pix_fmt yuv420p, নিচের ধাপে রক্ষণশীল প্রোফাইল।
৪. প্লে চাপার পর দীর্ঘ অপেক্ষা। কারণ: mp4-এর সূচি ফাইলের শেষে। সমাধান: faststart, বা HLS-এ যাওয়া।
৫. ঘোরানো ভিডিও উল্টো। কারণ: rotation মেটাডেটা পাইপলাইনের কোথাও হারিয়েছে। সমাধান: probe-এ ধরা, ফিল্টারে ঠিক করা।
৬. ডিস্ক ভরে যাওয়া। কারণ: ব্যর্থ কাজের অস্থায়ী ফাইল পড়ে থাকে। সমাধান: প্রতিটা কাজের নিজস্ব অস্থায়ী ফোল্ডার, আর নিশ্চিত পরিষ্কার; সাথে ডিস্ক ব্যবহারের অ্যালার্ট।
৭. থান্ডারিং হার্ড। লক্ষণ: জনপ্রিয় ভিডিও ছাড়ার প্রথম মিনিটে সবাই বাফার করছে। কারণ: CDN ক্যাশ ঠান্ডা, সবাই একসাথে মূল সার্ভারে যাচ্ছে। সমাধান: অরিজিন শিল্ড, আর আগেভাগে ক্যাশ গরম করা।
৮. নীরব কোয়ালিটি পতন। লক্ষণ: তিন সপ্তাহ পর কেউ খেয়াল করল ভিডিও খারাপ দেখাচ্ছে। কারণ: কেউ একটা সেটিংস বদলেছে। সমাধান: প্রতিটা কাজের পর নমুনার VMAF মেপে রাখা, আর মান নামলে অ্যালার্ট।
৯. অর্ধেক প্রকাশিত ভিডিও। কারণ: ফোল্ডারের অস্তিত্বকে সাফল্যের প্রমাণ ধরা হয়েছে। সমাধান: ডেটাবেসই সত্য, আর আউটপুট অস্থায়ী জায়গা থেকে শেষে সরানো।
১০. একই কাজ দুই ওয়ার্কার একসাথে করছে। লক্ষণ: আউটপুট ফাইল আধা-লেখা, এলোমেলো। কারণ: সারি থেকে কাজ তোলার সময় লক নেই, বা দখলের মেয়াদ খুব ছোট। সমাধান: skip locked, হার্টবিট, আর ওয়ার্কার প্রতি আলাদা আউটপুট পথ।
১১. ধীরে ধীরে ব্যয় বেড়ে যাওয়া। লক্ষণ: বিল প্রতি মাসে বাড়ছে, ট্রাফিক বাড়ছে না। কারণ: পুরনো ব্যর্থ কাজের ফাইল, অব্যবহৃত ধাপ, বা ক্যাশ কী-র ভুলে CDN কাজ করছে না। সমাধান: স্টোরেজের নিয়মিত হিসাব আর লাইফসাইকেল নীতি।
১২. HDR ইনপুট ধূসর হয়ে যায়। কারণ: টোন ম্যাপিং ছাড়া SDR-এ রূপান্তর। সমাধান: probe-এ HDR চেনা, আর আলাদা পথে পাঠানো।
১৩. ক্ষমতার হিসাব
কতগুলো ওয়ার্কার লাগবে, সেটা আন্দাজ না করে হিসাব করা যায়:
ধরা যাক:
দিনে আপলোড = ৫০০ ঘণ্টা ভিডিও
ল্যাডারে ধাপ = ৫টা
এক ওয়ার্কার এনকোড করে = রিয়েলটাইমের ২ গুণ গতিতে (সব ধাপ মিলিয়ে)
দিনে প্রয়োজন = ৫০০ ঘণ্টা ÷ ২ = ২৫০ ওয়ার্কার-ঘণ্টা
সমানভাবে ছড়ালে = ২৫০ ÷ ২৪ ≈ ১১ ওয়ার্কার
কিন্তু আপলোড সমান হয় না — ব্যস্ত সময়ে দিনের ৪০% কাজ আসে ৪ ঘণ্টায়:
ব্যস্ত সময়ের প্রয়োজন = (২৫০ × ০.৪) ÷ ৪ = ২৫ ওয়ার্কার
সিদ্ধান্ত: ভিত্তি ১০, সর্বোচ্চ ৩০, সারির গভীরতা দেখে স্কেল এই ছোট হিসাবটাই “কত মেশিন লাগবে” প্রশ্নের বাস্তব উত্তর দেয়, আর অটোস্কেলিংয়ের সীমাগুলো ঠিক করে দেয়।
১৪. ল্যাডার বদলানো আর পুরনো ভিডিও
ছয় মাস পর তুমি সিদ্ধান্ত নেবে AV1 যোগ করবে, বা ল্যাডার বদলাবে। তখন লাইব্রেরির লাখখানেক ভিডিওর কী হবে?
সব একসাথে আবার এনকোড করো না। বদলে:
- ল্যাডারের সংস্করণ রাখো প্রতিটা ভিডিওর সাথে।
- নতুন আপলোড নতুন সংস্করণে যাক।
- পুরনোগুলোর মধ্যে শুধু জনপ্রিয়গুলো ধীরে ধীরে আবার এনকোড করো — অলস সময়ে, কম অগ্রাধিকারের সারিতে।
- বাকিগুলো পুরনো সংস্করণেই থাক, বা চাহিদা এলে তখন রূপান্তর হোক।
এভাবে সবচেয়ে বেশি দেখা ভিডিওগুলোতেই সাশ্রয়টা আসে, আর বিলটা এক মাসে বিস্ফোরিত হয় না।
১৫. চূড়ান্ত চেকলিস্ট
ইনগেস্ট
- presigned, মাল্টিপার্ট আপলোড, সীমা বাঁধা
- হ্যাশ দিয়ে ডিডুপ
- probe প্রথমে, স্পষ্ট গ্রহণ/বর্জন নীতি
- ব্যবহারকারীকে বোধগম্য ভাষায় ভুল জানানো
কাজ ও সারি
- টেকসই সারি, স্পষ্ট স্টেট মেশিন
- ডেটাবেসই সত্যের উৎস
- আইডেম্পোটেন্সি কী (হ্যাশ + ল্যাডার সংস্করণ)
- মেয়াদসহ দখল + হার্টবিট
- ধরন অনুযায়ী রিট্রাই, dead letter, অ্যালার্ট
এনকোডিং
- ffmpeg সংস্করণ পিন করা
- কি-ফ্রেম নিয়ন্ত্রিত, সব ধাপে মিল
- ইনপুটের চেয়ে বড় ধাপ না
- বড় ভিডিওতে চাংকিং, অডিও আলাদা
- স্পট মেশিন ব্যবহারযোগ্য
প্যাকেজিং ও ডেলিভারি
- CMAF, প্যাকেজিং এনকোডিং থেকে আলাদা
- সইসহ URL, দরকার হলে DRM
- CDN, লম্বা TTL, সরল ক্যাশ কী, অরিজিন শিল্ড
পরিচালনা
- সারির বয়স, ব্যর্থতা, খরচের ড্যাশবোর্ড
- দর্শকের দিকের QoE সংগ্রহ ও ভাগ করে দেখা
- নমুনার VMAF, পতনে অ্যালার্ট
- স্টোরেজ লাইফসাইকেল নীতি
- অস্থায়ী ফাইল পরিষ্কারের নিশ্চয়তা
- ল্যাডার সংস্করণ ও ধীরে ধীরে পুনঃএনকোডের পরিকল্পনা
শেষ কথা
তিন পর্বে আমরা যা করলাম:
পর্ব ১ — ভিডিও আসলে ছবির স্তূপ; কম্প্রেশন কাজ করে কারণ পাশের ফ্রেম প্রায় একই আর চোখ সবকিছু দেখে না; আধুনিক স্ট্রিমিং মানে ভিডিওকে ছোট টুকরোয় কেটে কয়েকটা ধাপে রাখা, আর প্লেয়ার নিজে বেছে নেওয়া।
পর্ব ২ — সেই তত্ত্বটা হাতে করা: probe, ল্যাডার, কি-ফ্রেম বাঁধা, HLS প্যাকেজিং, থাম্বনেইল, সাবটাইটেল, আর একটা ওয়ার্কার।
পর্ব ৩ — সেই খেলনাটাকে সিস্টেম বানানো: ধাপ আলাদা করা, সমান্তরালে চালানো, ব্যর্থতা সামলানো, খরচ আর দর্শকের অভিজ্ঞতা মাপা।
সবচেয়ে বড় শিক্ষাটা হয়তো এই — ভিডিও ইঞ্জিনিয়ারিংয়ের কঠিন অংশটা কোডেকের গণিত না। কোডেকের কাজ ffmpeg করে দেয়। কঠিন অংশটা সিস্টেমের কাজ: সারি, অবস্থা, ব্যর্থতা, স্টোরেজ, খরচ, আর ভাঙা ইনপুট। এই জিনিসগুলো ভিডিও-নির্দিষ্টও না — যেকোনো ভারী কাজের পাইপলাইনে একই সমস্যা ফিরে আসে।
আর সব সিদ্ধান্তের শেষে একটাই প্রশ্ন — সমরকন্দে বাসে বসে থাকা মানুষটা প্লে চাপল, সে কি ভিডিওটা দেখতে পেল?