راه‌اندازی پخش زنده روی سایت یعنی سه قطعه را به هم وصل کنید. یک ورودی RTMP تصویر را از نرم‌افزار ضبط می‌گیرد، یک بخش آن را به قطعه‌های HLS می‌برد و یک پلیر در مرورگر بیننده پخش می‌کند. ماژول RTMP برای nginx هر سه کار را روی یک سرور انجام می‌دهد.

قطعه زنجیرهابزارآنچه تنظیم می‌کنید
فرستندهنرم‌افزار OBS یا FFmpegنشانی rtmp و کلید استریم
ورودی سروربلوک rtmp در nginx.confدایرکتیو listen روی پورت 1935 و یک application
تبدیل به قطعههمان ماژول RTMPدایرکتیوهای hls، hls_path و hls_fragment
تحویل به بینندهبلوک server در httpسرو کردن پوشه HLS با HTTPS
پخشکتابخانه hls.jsیک تگ video و نشانی m3u8

💡 خلاصه فنی پیش از شروع

ماژول RTMP یک افزونه جداگانه برای nginx است؛ nginx خالی این قابلیت را ندارد.
✅ در دبیان و اوبونتو بسته آماده libnginx-mod-rtmp ماژول را داینامیک نصب و خودش فعال می‌کند، پس خط load_module لازم نیست.
✅ بلوک rtmp فقط در سطح main فایل /etc/nginx/nginx.conf معتبر است، نه در sites-available.

بیشتر راهنماهای این موضوع فهرست دستورهای نصب را می‌آورند و همان‌جا تمام می‌شوند. اما چیزی که بعد از اولین پخش موفق دردسر می‌سازد، دستور نصب نیست. حجم ترافیکی است که از پورت سرور بیرون می‌رود و تأخیری که بیننده می‌بیند. پس ترتیب این مقاله برعکس است: اول مسیر ویدیو، بعد انتخاب بیلد و تنظیم، و در پایان حساب مصرف. برای زیرساخت یک سرور مجازی ایران کافی است.

نمودار مسیر ویدیو از نرم‌افزار ضبط تا مرورگر بیننده روی سرور nginx، راه اندازی پخش زنده روی سایت

زنجیره راه‌اندازی پخش زنده روی سایت از OBS تا مرورگر

تصویر شما با پروتکل RTMP و پورت 1935 به سرور می‌رسد و در یک application داخل بلوک rtmp دریافت می‌شود. همان‌جا به قطعه‌های چندثانیه‌ای و یک پلی‌لیست m3u8 روی دیسک تبدیل می‌شود. بلوک http هم این فایل‌ها را مثل محتوای ساده سایت به پلیر می‌دهد.

ورودی: چرا هنوز RTMP

پروتکل RTMP قدیمی است و پلیرش سال‌ها پیش از مرورگرها حذف شد، ولی در سمت ارسال باقی ماند. نرم‌افزارهای ضبط مثل OBS و دستور FFmpeg همین را مقصد پیش‌فرض می‌شناسند.

یک نکته امنیتی را از همین‌جا بدانید: ترافیک RTMP در این ماژول رمزنگاری نمی‌شود. پس کلید استریم به شکل متن ساده روی شبکه می‌رود و باید انتشار را محدود کنید.

خروجی: ساختار قطعه‌ها و فایل m3u8

ماژول، جریان ورودی را به فایل‌های کوتاه با پسوند ts و یک فایل m3u8 می‌شکند. فایل m3u8 فهرست نام و مدت قطعه‌ها است و پلیر هر چند ثانیه آن را دوباره می‌خواند. مشخصات این قالب در RFC 8216 ثبت شده و همین باعث می‌شود پخش HLS در iOS و سافاری بدون کتابخانه جاوااسکریپتی کار کند.

🔸 مسیر داده روی سرور

مسیر داده این‌گونه است.
OBS → rtmp://IP:1935/src → nginx (rtmp) → /var/www/hls/src/<name>/index.m3u8 + قطعه‌های ts → nginx (http, 443) → پلیر مرورگر

کدام بیلد nginx ماژول RTMP را دارد؟

ماژول RTMP در nginx رسمی گنجانده نشده و باید جداگانه بیاید. سه مسیر دارید: بسته داینامیک آماده در دبیان و اوبونتو، کامپایل nginx از سورس با --add-dynamic-module، و ماژول تجاری روی NGINX Plus. اولین قدم راه‌اندازی پخش زنده روی سایت همین انتخاب است، چون محل فایل تنظیم و روش ارتقا را عوض می‌کند.

سیستم‌عاملمسیر پیشنهادینکته
اوبونتو و دبیانبسته libnginx-mod-rtmpدر دبیان از مخزن رسمی و در اوبونتو از بخش universe؛ خودش فعال می‌شود
آلمالینوکس و راکیکامپایل از سورس یا مخزن ثالثمسیر رایج، کامپایل است
نسخه دلخواه nginxکامپایل با add-dynamic-moduleکنترل کامل، ولی هر ارتقا دوباره کامپایل می‌خواهد
NGINX Plusبسته nginx-plus-module-rtmpمسیر تجاری و پشتیبانی‌شده با دستور load_module

روش اول: بسته آماده در اوبونتو و دبیان

ساده‌ترین مسیر همین است. بسته libnginx-mod-rtmp فایل ماژول را در /usr/lib/nginx/modules/ می‌گذارد و فایل فعال‌سازی را از modules-available به modules-enabled می‌برد. پس ماژول از همان لحظه بار می‌شود و نباید load_module را دستی اضافه کنید، وگرنه nginx -t با خطای بارگذاری دوباره رد می‌شود.

sudo apt update
sudo apt install nginx libnginx-mod-rtmp ffmpeg
ls /etc/nginx/modules-enabled/
sudo systemctl restart nginx

یک محدودیت را در نظر بگیرید: نسخه این بسته به نسخه nginx همان مخزن قفل است، چون وابستگی آن روی بسته ABI نوشته شده. اگر nginx را از مخزن nginx.org نصب کرده باشید، باید سراغ روش دوم بروید.

روش دوم: کامپایل از سورس

طبق مستندات configure در nginx.org، گزینه --add-module=path یک ماژول بیرونی را ثابت داخل باینری می‌برد و --add-dynamic-module=path همان ماژول را داینامیک می‌سازد تا با load_module بارگذاری شود. نسخه داینامیک را انتخاب کنید؛ ارتقای nginx ساده‌تر می‌شود.

sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev git
git clone https://github.com/arut/nginx-rtmp-module.git
wget https://nginx.org/download/nginx-1.30.6.tar.gz
tar xf nginx-1.30.6.tar.gz && cd nginx-1.30.6
./configure --with-http_ssl_module --add-dynamic-module=../nginx-rtmp-module
make && sudo make install

نسخه stable روی nginx.org در زمان نوشتن این مقاله 1.30.6 و mainline 1.31.8 است؛ شماره را از همان صفحه دانلود بردارید. اگر nginx را قبلاً با apt نصب کرده‌اید، make install نکنید. این کار یک nginx دوم با مسیر و سرویس جدا می‌سازد. به‌جایش خروجی nginx -V را بردارید و همان گزینه‌ها را با افزودن ماژول دوباره اجرا کنید.

روی NGINX Plus هم بسته nginx-plus-module-rtmp از مخزن رسمی نصب و با خط load_module modules/ngx_rtmp_module.so; در سطح main بارگذاری می‌شود.

⚠️ یک نکته درباره نگهداری ماژول

این ماژول بخشی از پروژه nginx نیست و با چرخه انتشار آن هم‌قدم نمی‌شود. پس پیش از ارتقای nginx، روی یک سرور تست بیلد را بسازید و پخش را امتحان کنید.

کدام بیلد nginx ماژول RTMP را دارد؟

تنظیم بلوک rtmp و سرو کردن HLS روی دامنه

تنظیم از دو تکه ساخته می‌شود که در دو جای متفاوت می‌نشینند. بلوک rtmp باید در سطح main فایل /etc/nginx/nginx.conf و بیرون از http {} باشد؛ بلوک server مثل هر سایت دیگر در /etc/nginx/sites-available/live.conf می‌رود و به sites-enabled لینک می‌شود. هسته کار همین دو تکه است و بقیه، تنظیم امنیت و کیفیت است.

بلوک rtmp و دایرکتیوهای HLS

دایرکتیوهای این بلوک پیش‌فرض‌های مستندشده دارند و همین‌ها لحن راه‌اندازی پخش زنده روی سایت را تعیین می‌کنند: hls_fragment پنج ثانیه، hls_playlist_length سی ثانیه، hls_nested خاموش و hls_cleanup روشن. مقدار chunk_size هم پیش‌فرض 4096 است.

# /etc/nginx/nginx.conf  (سطح main، بیرون از http)
rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application src {
            live on;
            record off;
            hls on;
            hls_path /var/www/hls/src;
            hls_fragment 4s;
            hls_playlist_length 20s;
            hls_nested on;
            hls_cleanup on;
            drop_idle_publisher 10s;

            allow publish 192.0.2.10;   # IP اتاق ضبط خودتان
            deny publish all;
            allow play all;
        }
    }
}
  • دایرکتیو hls_fragment 4s: طول هر قطعه. هرچه کوچک‌تر، تأخیر کمتر و درخواست HTTP بیشتر.
  • دایرکتیو hls_playlist_length 20s: عمق پلی‌لیست، یعنی پلیر چند قطعه گذشته را می‌بیند.
  • دایرکتیو hls_nested on: برای هر نام استریم یک پوشه جدا می‌سازد.
  • دایرکتیو hls_cleanup on: قطعه‌های بیرون‌افتاده از پلی‌لیست را پاک می‌کند.
  • دایرکتیو drop_idle_publisher 10s: اتصال فرستنده بی‌داده را می‌بندد.

دایرکتیو hls_path اگر پوشه نباشد خودش می‌سازد، پس نگرانی اصلی مجوز نوشتن در مسیر والد است. کاربر اجراکننده nginx در دبیان و اوبونتو www-data و در آلما و راکی nginx است. مسیر را پیش از زدن Enter دوباره بخوانید، چون chown -R روی مسیر اشتباه جبران‌ناپذیر است.

سرو کردن پوشه روی دامنه

قطعه‌ها فایل ساده هستند، پس بلوک server همیشگی کار را انجام می‌دهد. سه چیز را تنظیم کنید: گواهی TLS، نوع MIME فایل‌های m3u8 و ts، و هدر Cache-Control روی no-cache، چون پلیر پلی‌لیست را مدام دوباره می‌خواند.

# /etc/nginx/sites-available/live.conf
server {
    listen 443 ssl;
    server_name live.example.ir;

    ssl_certificate     /etc/letsencrypt/live/live.example.ir/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/live.example.ir/privkey.pem;

    location /hls/ {
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        root /var/www;
        add_header Cache-Control no-cache always;
    }
}

بدون دو خط گواهی، nginx با خطای نبودن ssl_certificate بالا نمی‌آید. در نسخه‌های تازه، فایل mime.types خود nginx هر دو نوع را دارد و بلوک types محض اطمینان است. دقت کنید که root /var/www با مسیر /hls/ به همان hls_path می‌رسد. در پایان sudo nginx -t و سپس reload.

پلیر در مرورگر

کتابخانه hls.js طبق مستندات خودش فقط روی مرورگرهای دارای Media Source Extensions کار می‌کند و پیشنهاد می‌دهد اول Hls.isSupported() را بسنجید. همان مستندات می‌گوید canPlayType در کروم هم مقدار غیرخالی برمی‌گرداند ولی پشتیبانی همه‌جا یکسان نیست، پس ترتیب سنجش مهم است. سافاری نشانی m3u8 را مستقیم در تگ video باز می‌کند.

<video id="live" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
  var v = document.getElementById('live');
  var src = 'https://live.example.ir/hls/src/mystream/index.m3u8';
  if (window.Hls && Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(src);
    hls.attachMedia(v);
  } else if (v.canPlayType('application/vnd.apple.mpegurl')) {
    v.src = src;
  }
</script>

کلید استریم و محدود کردن انتشار

در OBS نوع سرویس را Custom بگذارید، در فیلد Server نشانی rtmp://IP:1935/src و در فیلد Stream Key نام استریم را بنویسید. همین نام در مسیر پلی‌لیست ظاهر می‌شود، پس قابل حدس نگذارید. در فایروال هم پورت را فقط به همان IP باز کنید: sudo ufw allow from 192.0.2.10 to any port 1935 proto tcp.

برای کنترل جدی‌تر دو ابزار دیگر هم دارید. نشانی 192.0.2.10 در نمونه‌ها یک آدرس مستندسازی است و اگر عوضش نکنید هیچ‌کس نمی‌تواند پخش کند. دایرکتیو on_publish نشانی یک وب‌سرویس را پیش از شروع پخش صدا می‌زند؛ پاسخ موفق اجازه می‌دهد و ناموفق اتصال را رد می‌کند، پس توکن یک‌بارمصرف ممکن می‌شود. تفاوت مفهومی دو حالت پخش را در راهنمای تفاوت استریمینگ و برادکستینگ آورده‌ایم.

حساب‌وکتاب پهنای باند و تأخیر در راه‌اندازی پخش زنده روی سایت

حساب‌وکتاب پهنای باند و تأخیر در راه‌اندازی پخش زنده روی سایت

هزینه‌های این معماری قابل محاسبه است. ترافیک خروجی از مجموع نرخ بیت بیننده‌ها می‌آید و تأخیر از طول قطعه و عمق پلی‌لیست ساخته می‌شود. بار پردازنده هم با هر کیفیت اضافه بالا می‌رود. این عددها را با مقدارهای تنظیم خودتان حساب کنید، نه با عدد نمونه مقاله‌ها.

فرمول ترافیک و پهنای باند

ویدیو با نرخ بیت ثابت بیرون می‌رود، پس حساب آن ضرب ساده است. نرخ بیت هر کیفیت را در تعداد بیننده همان کیفیت ضرب کنید و جمع بزنید. برای حجم ترافیک هم یک مگابیت بر ثانیه در یک ساعت برابر 450 مگابایت است (3600 تقسیم بر 8).

  • پهنای باند لحظه‌ای (مگابیت بر ثانیه) = مجموع (نرخ بیت هر کیفیت × تعداد بیننده آن کیفیت)
  • ترافیک هر بیننده در ساعت (مگابایت) = نرخ بیت آن کیفیت × 450
  • ترافیک کل رویداد = ترافیک هر بیننده در ساعت × ساعت پخش × تعداد بیننده
کیفیتنرخ بیت ویدیو و صدامصرف یک بیننده در یک ساعت
720p2500 + 128 کیلوبیت بر ثانیهحدود ۱.۲ گیگابایت
480p900 + 96 کیلوبیت بر ثانیهحدود ۴۵۰ مگابایت
360p600 + 64 کیلوبیت بر ثانیهحدود ۳۰۰ مگابایت

عدد ستون آخر از همان فرمول درآمده و گرد شده است. قالب MPEG-TS و درخواست‌های مکرر پلی‌لیست هم سرباری دارند. بهتر است اندازه‌اش را بگیرید: یک پخش کوتاه انجام دهید، حجم پوشه خروجی را با du -sh /var/www/hls ببینید و تقسیم بر مدت پخش کنید.

🔶 نکته زیرساخت

برای تماشای بیننده‌ها باید فایل‌های HLS از اینترنت در دسترس باشند. سرور مجازی ایران وب‌داده IP مستقیم دارد که از اینترنت بین‌الملل هم قابل دسترسی است و IPv4 و IPv6 را پشتیبانی می‌کند. پنل آن اسنپ‌شات هم دارد، پس پیش از دست‌کاری تنظیم nginx یک اسنپ‌شات بگیرید.

تأخیر را از روی تنظیم خودتان حساب کنید

تأخیر HLS تصادفی نیست و بیشترش از دو عددی می‌آید که خودتان نوشته‌اید. قطعه‌ای که در حال ساخت است تا کامل نشود در پلی‌لیست نمی‌آید و پلیر هم پیش از شروع، چند قطعه را بافر می‌کند. پس با hls_fragment 4s فاصله واقعیت و تصویر بیننده معمولاً از ده ثانیه بالاتر می‌رود.

کم کردن hls_fragment تأخیر را پایین می‌آورد، ولی تعداد فایل و درخواست HTTP را بالا می‌برد. یک نکته را از خود مستندات ماژول بردارید: برش قطعه‌ها دایرکتیو جدای hls_fragment_slicing دارد و برای شروع جریان از فریم کلیدی هم wait_key هست که پیش‌فرضش خاموش است. در عمل فاصله فریم‌های کلیدی فرستنده را با طول قطعه هم‌اندازه کنید؛ در FFmpeg همان -g است که مستندات آن را اندازه GOP تعریف کرده. برای 30 فریم و قطعه 4 ثانیه یعنی -g 120.

اگر کاربرد شما تأخیر زیر چند ثانیه می‌خواهد، مثل مزایده یا کلاس تعاملی، فهرست دایرکتیوهای این ماژول چنین چیزی را پوشش نمی‌دهد و باید سراغ پروتکل‌های کم‌تأخیر بروید.

هزینه ترانسکد چند کیفیتی

اگر بیننده‌ها اینترنت یکسانی ندارند، به چند کیفیت نیاز دارید و این یعنی ترانسکد. دایرکتیو exec هنگام شروع پخش یک دستور بیرونی را اجرا می‌کند. مستندات ماژول دو شرط دارد: مسیر کامل باینری را بنویسید و چون nginx محیط را پاک می‌کند، env PATH; را هم نگه دارید. بلوک زیر جایگزین application src قبلی است و دو application خروجی را هم اضافه می‌کند.

env PATH;

application src {
    live on;
    hls on;
    hls_path /var/www/hls/src;
    allow publish 192.0.2.10;
    deny publish all;

    exec /usr/bin/ffmpeg -i rtmp://127.0.0.1:1935/src/$name
      -c:a aac -b:a 128k -c:v libx264 -preset veryfast -b:v 2500k -maxrate 2500k -bufsize 5000k -g 120 -s 1280x720 -f flv rtmp://127.0.0.1:1935/hls720/$name
      -c:a aac -b:a 96k  -c:v libx264 -preset veryfast -b:v 900k  -maxrate 900k  -bufsize 1800k -g 120 -s 854x480  -f flv rtmp://127.0.0.1:1935/hls480/$name;
}

application hls720 {
    live on;
    hls on;
    hls_nested on;
    hls_path /var/www/hls/720;
    allow publish 127.0.0.1;
    deny publish all;
}

# application hls480 هم همین پنج خط را با hls_path /var/www/hls/480 می‌گیرد

دو خط deny publish all در application‌های خروجی اختیاری نیستند. پیش‌فرض کنترل دسترسی این ماژول اجازه دادن است، پس بدون آن‌ها هر کسی می‌تواند روی همان نام پخش کند و تصویرش روی سایت شما برود. مستندات FFmpeg هم -maxrate را سقف تحمل نرخ بیت تعریف کرده که به -bufsize نیاز دارد.

هزینه را بی‌تعارف بگوییم: کدکردن نرم‌افزاری با libx264 سنگین‌ترین بخش این معماری است و هر کیفیت اضافه بار تازه‌ای روی پردازنده می‌گذارد. عدد قطعی برای تعداد هسته وجود ندارد، چون به رزولوشن، نرخ فریم و مقدار -preset بستگی دارد. با یک کیفیت شروع کنید و مصرف را با top ببینید. اگر پردازنده جواب نداد، با -c:v copy همان کیفیت فرستنده را پخش کنید.

برای اینکه پلیر بین کیفیت‌ها جابه‌جا شود، یک پلی‌لیست مادر در /var/www/hls/live.m3u8 بسازید و نشانی https://live.example.ir/hls/live.m3u8 را به پلیر بدهید.

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2"
/hls/720/mystream/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1100000,RESOLUTION=854x480,CODECS="avc1.4d401e,mp4a.40.2"
/hls/480/mystream/index.m3u8

برای رفع خطا سه دستور کافی است: curl -I https://live.example.ir/hls/720/mystream/index.m3u8 برای سنجش Content-Type، tail -f /var/log/nginx/error.log برای خطای ماژول، و ffprobe rtmp://127.0.0.1:1935/src/mystream برای دیدن جریان ورودی.

حق پخش هر محتوایی که روی این سرور می‌فرستید باید متعلق به خودتان باشد یا مجوز داشته باشید.

پورت 1935 را باید روی فایروال باز کنم؟

بله، پورت 1935 مسیر ورود تصویر است و باید برای IP فرستنده باز باشد. برای بیننده‌ها لازم نیست، چون تماشا روی پورت 443 انجام می‌شود.

از نظر فنی بله، چون قطعه‌ها روی HTTP ساده هم سرو می‌شوند. ولی اگر سایت شما روی HTTPS باشد، مرورگر محتوای HTTP را بلاک می‌کند و پلیر چیزی نشان نمی‌دهد.

کروم به کتابخانه‌ای نیاز دارد که از Media Source Extensions استفاده کند و پخش بومی آن مثل سافاری کامل نیست. اول نوع MIME را با curl بسنجید، بعد لود شدن کتابخانه را در کنسول مرورگر.

طول قطعه و عمق پلی‌لیست را کم کنید و فاصله فریم کلیدی فرستنده را با طول قطعه هماهنگ کنید. به جایی می‌رسید که کم کردن بیشتر پخش را ناپایدار می‌کند؛ برای تأخیر زیر چند ثانیه این ماژول مناسب نیست.

دایرکتیو record حالت‌هایی مثل all و keyframes می‌گیرد و مسیر ذخیره با record_path تعیین می‌شود. حواستان به فضای دیسک باشد، چون فایل ضبط جدا از قطعه‌های HLS نگه داشته می‌شود.

با روشن بودن hls_cleanup که پیش‌فرض است، قطعه‌های بیرون‌افتاده از پلی‌لیست پاک می‌شوند. اگر آن را خاموش کنید، باید خودتان چرخه پاک‌سازی بنویسید.

بله، دایرکتیو push جریان یک application را به نشانی RTMP دیگری ارسال می‌کند. هر مقصد اضافه پهنای باند خروجی سرور را بیشتر می‌کند.

همین ماژول دایرکتیوهای dash و dash_path را هم دارد. تفاوت عملی در پشتیبانی پلیرها است: HLS روی iOS و سافاری بومی کار می‌کند و DASH به کتابخانه پلیر نیاز دارد.

جمع‌بندی؛ راه‌اندازی پخش زنده روی سایت از نصب تا حساب ترافیک
این کار سه مرحله روشن دارد. اول بیلدی از nginx را انتخاب می‌کنید که ماژول RTMP داشته باشد؛ در دبیان و اوبونتو بسته libnginx-mod-rtmp سریع‌ترین راه است و خودش ماژول را فعال می‌کند. دوم بلوک rtmp را در سطح main فایل nginx.conf می‌نویسید تا ورودی پورت 1935 را بگیرد و قطعه‌ها را بسازد. بعد همان پوشه را با گواهی TLS و نوع MIME درست روی دامنه سرو می‌کنید و در مرورگر با hls.js نشان می‌دهید. سوم، و مهم‌تر از آنچه به نظر می‌رسد، عددها را خودتان حساب می‌کنید: ترافیک از ضرب نرخ بیت در تعداد بیننده و ساعت پخش، و تأخیر از طول قطعه و عمق پلی‌لیست. دو محدودیت را هم در نظر بگیرید؛ این ماژول برای تأخیر زیر چند ثانیه ساخته نشده و ترافیک RTMP ورودی رمزنگاری نمی‌شود. اگر ترانسکد چندکیفیتی می‌سازید، application‌های خروجی را هم با deny publish all ببندید.

🚀 زیرساخت پخش را روی سرور خودتان بسازید

برای ورودی RTMP و تحویل HLS به یک سرور با IP مستقیم و منابع قابل ارتقا نیاز دارید. امکان تست ساعتی رایگان سرور هم هست تا پیش از رویداد، تنظیم را بسنجید.

اگر در تنظیم بلوک rtmp یا پخش در مرورگر به مشکلی خوردید، نسخه nginx و خروجی nginx -t را در کامنت بنویسید.

منابع

وب داده
وب داده

جدید ترین مطالب آموزشی و کاربردی را در اینجا بخوانید !
ما با بهره‌گیری از دانش روز و تجربه متخصصان حوزه فناوری، مجموعه‌ای از آموزش‌های کاربردی و مقالات تخصصی را گردآوری کرده‌ایم که هر یک، پاسخی دقیق به پرسش‌های شماست. ؛ از مفاهیم پایه تا پیچیده‌ترین تکنیک‌های حرفه‌ای. اینجا، دانش با زبانی ساده اما عمیق در اختیار شما قرار می‌گیرد.

مقاله‌ها: 244
پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *