இந்த கட்டுரையில், அடோப் ஃப்ளாஷ் பிளேயர் போன்ற மூன்றாம் தரப்பு உலாவி செருகுநிரல்களைப் பயன்படுத்தாமல் வெப்சாக்கெட்டுகள் வழியாக வீடியோவை ஸ்ட்ரீம் செய்வதற்கான எனது முயற்சிகளைப் பகிர்ந்து கொள்ள விரும்புகிறேன். அதில் என்ன வந்தது என்பதை அறிய தொடர்ந்து படியுங்கள்.
அடோப் ஃப்ளாஷ், முன்பு மேக்ரோமீடியா ஃப்ளாஷ், இணைய உலாவியில் இயங்கும் பயன்பாடுகளை உருவாக்குவதற்கான ஒரு தளமாகும். மீடியா ஸ்ட்ரீம் ஏபிஐ அறிமுகப்படுத்தப்படுவதற்கு முன்பு, வெப்கேமில் இருந்து வீடியோ மற்றும் குரலை ஸ்ட்ரீமிங் செய்வதற்கும், உலாவியில் பல்வேறு வகையான மாநாடுகள் மற்றும் அரட்டைகளை உருவாக்குவதற்கும் இது நடைமுறையில் ஒரே தளமாக இருந்தது. RTMP (Real Time Messaging Protocol) என்ற ஊடகத் தகவலை அனுப்புவதற்கான நெறிமுறை நீண்ட காலமாக மூடப்பட்டது, இதன் பொருள்: உங்கள் ஸ்ட்ரீமிங் சேவையை அதிகரிக்க விரும்பினால், Adobe-ல் இருந்து மென்பொருளைப் பயன்படுத்துவதற்கு போதுமான தயவு - Adobe Media Server (AMS).
2012 இல் சிறிது நேரம் கழித்து, அடோப் பொதுமக்களிடம் "கைவிட்டு அதை துப்பியது".
அடோப் ஃப்ளாஷ் இயங்குதளம் 20 ஆண்டுகளுக்கும் மேலாக பழமையானது, இந்த நேரத்தில் பல முக்கியமான பாதிப்புகள் கண்டறியப்பட்டுள்ளன, ஆதரவு
எனது திட்டத்திற்காக, உலாவியில் ஃப்ளாஷ் பயன்பாட்டை முற்றிலுமாக கைவிட உடனடியாக முடிவு செய்தேன். மேலே உள்ள முக்கிய காரணத்தை நான் சுட்டிக்காட்டினேன்; மொபைல் பிளாட்ஃபார்ம்களில் ஃப்ளாஷ் ஆதரிக்கப்படவில்லை, மேலும் விண்டோஸில் (வைன் எமுலேட்டர்) மேம்பாட்டிற்காக அடோப் ஃப்ளாஷ் பயன்படுத்த விரும்பவில்லை. எனவே நான் ஜாவாஸ்கிரிப்டில் ஒரு கிளையண்டை எழுதத் தொடங்கினேன். இது ஒரு முன்மாதிரியாக மட்டுமே இருக்கும், ஏனெனில் p2p அடிப்படையில் ஸ்ட்ரீமிங்கை மிகவும் திறமையாகச் செய்ய முடியும் என்பதை நான் பின்னர் அறிந்தேன், எனக்கு மட்டுமே அது peer - server - peers ஆக இருக்கும், ஆனால் அது இன்னும் தயாராக இல்லை என்பதால் மற்றொரு முறை.
தொடங்குவதற்கு, எங்களுக்கு உண்மையான வெப்சாக்கெட் சேவையகம் தேவை. மெலடி கோ தொகுப்பின் அடிப்படையில் எளிமையான ஒன்றை உருவாக்கினேன்:
சர்வர் குறியீடு
package main
import (
"errors"
"github.com/go-chi/chi"
"gopkg.in/olahol/melody.v1"
"log"
"net/http"
"time"
)
func main() {
r := chi.NewRouter()
m := melody.New()
m.Config.MaxMessageSize = 204800
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/index.html")
})
r.Get("/ws", func(w http.ResponseWriter, r *http.Request) {
m.HandleRequest(w, r)
})
// Бродкастим видео поток
m.HandleMessageBinary(func(s *melody.Session, msg []byte) {
m.BroadcastBinary(msg)
})
log.Println("Starting server...")
http.ListenAndServe(":3000", r)
}
கிளையண்டில் (ஸ்ட்ரீமிங் பக்கத்தில்), நீங்கள் முதலில் கேமராவை அணுக வேண்டும். இது மூலம் செய்யப்படுகிறது
கேமரா/மைக்ரோஃபோனுக்கான அணுகலை (அனுமதி) பெறுகிறோம்
அடுத்து, getUserMedia() ஒரு வாக்குறுதியை வழங்குகிறது, அது மீடியாஸ்ட்ரீம் பொருளை அனுப்புகிறது - வீடியோ-ஆடியோ தரவின் ஸ்ட்ரீம். வீடியோ உறுப்பின் src பண்புக்கு இந்தப் பொருளை ஒதுக்குகிறோம். குறியீடு:
ஒளிபரப்பு பக்கம்
<style>
#videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>
<script type="application/javascript">
var
video = document.getElementById('videoObjectHtml5ApiServer');
// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
// видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать
video.srcObject = stream;
});
}
</script>
சாக்கெட்டுகளில் வீடியோ ஸ்ட்ரீமை ஒளிபரப்ப, நீங்கள் அதை எங்காவது குறியாக்கம் செய்து, அதை இடையகப்படுத்தி, பகுதிகளாக அனுப்ப வேண்டும். மூல வீடியோ ஸ்ட்ரீமை வெப்சாக்கெட்டுகள் வழியாக அனுப்ப முடியாது. இங்குதான் நமக்கு உதவி வருகிறது
நாங்கள் வீடியோ ஸ்ட்ரீமை குறியாக்குகிறோம், அதை துண்டுகளாக உடைக்கிறோம்
<style>
#videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>
<script type="application/javascript">
var
video = document.getElementById('videoObjectHtml5ApiServer');
// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
// видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать
video.srcObject = s;
var
recorderOptions = {
mimeType: 'video/webm; codecs=vp8' // будем кодировать видеопоток в формат webm кодеком vp8
},
mediaRecorder = new MediaRecorder(s, recorderOptions ); // объект MediaRecorder
mediaRecorder.ondataavailable = function(e) {
if (e.data && e.data.size > 0) {
// получаем кусочек видеопотока в e.data
}
}
mediaRecorder.start(100); // делит поток на кусочки по 100 мс каждый
});
}
</script>
இப்போது websockets வழியாக பரிமாற்றத்தைச் சேர்ப்போம். ஆச்சரியம் என்னவென்றால், இதற்கு உங்களுக்கு தேவையானது ஒரு பொருள் மட்டுமே
நாங்கள் வீடியோ ஸ்ட்ரீமை சேவையகத்திற்கு அனுப்புகிறோம்
<style>
#videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>
<script type="application/javascript">
var
video = document.getElementById('videoObjectHtml5ApiServer');
// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
// видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать
video.srcObject = s;
var
recorderOptions = {
mimeType: 'video/webm; codecs=vp8' // будем кодировать видеопоток в формат webm кодеком vp8
},
mediaRecorder = new MediaRecorder(s, recorderOptions ), // объект MediaRecorder
socket = new WebSocket('ws://127.0.0.1:3000/ws');
mediaRecorder.ondataavailable = function(e) {
if (e.data && e.data.size > 0) {
// получаем кусочек видеопотока в e.data
socket.send(e.data);
}
}
mediaRecorder.start(100); // делит поток на кусочки по 100 мс каждый
}).catch(function (err) { console.log(err); });
}
</script>
ஒளிபரப்பு பக்கம் தயாராக உள்ளது! இப்போது வீடியோ ஸ்ட்ரீமைப் பெற்று அதை கிளையண்டில் காண்பிக்க முயற்சிப்போம். இதற்கு நமக்கு என்ன தேவை? முதலில், நிச்சயமாக, சாக்கெட் இணைப்பு. WebSocket பொருளுடன் "கேட்பவரை" இணைத்து 'செய்தி' நிகழ்வுக்கு குழுசேருவோம். பைனரி தரவின் ஒரு பகுதியைப் பெற்ற பிறகு, எங்கள் சேவையகம் அதை சந்தாதாரர்களுக்கு, அதாவது வாடிக்கையாளர்களுக்கு ஒளிபரப்புகிறது. இந்த வழக்கில், 'செய்தி' நிகழ்வின் "கேட்பவர்" உடன் தொடர்புடைய கால்பேக் செயல்பாடு கிளையண்டில் தூண்டப்படுகிறது; பொருளே செயல்பாட்டு வாதத்திற்கு அனுப்பப்படுகிறது - vp8 ஆல் குறியிடப்பட்ட வீடியோ ஸ்ட்ரீமின் ஒரு பகுதி.
வீடியோ ஸ்ட்ரீமை ஏற்கிறோம்
<style>
#videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть тебя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>
<script type="application/javascript">
var
video = document.getElementById('videoObjectHtml5ApiServer'),
socket = new WebSocket('ws://127.0.0.1:3000/ws'),
arrayOfBlobs = [];
socket.addEventListener('message', function (event) {
// "кладем" полученный кусочек в массив
arrayOfBlobs.push(event.data);
// здесь будем читать кусочки
readChunk();
});
</script>
பெறப்பட்ட துண்டுகளை உடனடியாக வீடியோ உறுப்புக்கு பிளேபேக்கிற்கு அனுப்புவது ஏன் சாத்தியமில்லை என்பதை நீண்ட காலமாக நான் புரிந்து கொள்ள முயற்சித்தேன், ஆனால் இதைச் செய்ய முடியாது என்று மாறியது, நிச்சயமாக, நீங்கள் முதலில் அதை ஒரு சிறப்பு இடையகத்தில் வைக்க வேண்டும். வீடியோ உறுப்பு, அப்போதுதான் அது வீடியோ ஸ்ட்ரீமை இயக்கத் தொடங்கும். இதற்கு உங்களுக்கு தேவைப்படும்
மீடியா சோர்ஸ் மீடியா பிளேபேக் பொருளுக்கும் இந்த மீடியா ஸ்ட்ரீமின் மூலத்திற்கும் இடையில் ஒரு வகையான இடைத்தரகராக செயல்படுகிறது. MediaSource ஆப்ஜெக்டில் வீடியோ/ஆடியோ ஸ்ட்ரீமின் மூலத்திற்கான சொருகக்கூடிய பஃபர் உள்ளது. ஒரு அம்சம் என்னவென்றால், இடையகமானது Uint8 தரவை மட்டுமே வைத்திருக்க முடியும், எனவே அத்தகைய இடையகத்தை உருவாக்க உங்களுக்கு FileReader தேவைப்படும். குறியீட்டைப் பாருங்கள், அது இன்னும் தெளிவாகிவிடும்:
வீடியோ ஸ்ட்ரீமை இயக்குகிறது
<style>
#videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть тебя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>
<script type="application/javascript">
var
video = document.getElementById('videoObjectHtml5ApiServer'),
socket = new WebSocket('ws://127.0.0.1:3000/ws'),
mediaSource = new MediaSource(), // объект MediaSource
vid2url = URL.createObjectURL(mediaSource), // создаем объект URL для связывания видеопотока с проигрывателем
arrayOfBlobs = [],
sourceBuffer = null; // буфер, пока нуль-объект
socket.addEventListener('message', function (event) {
// "кладем" полученный кусочек в массив
arrayOfBlobs.push(event.data);
// здесь будем читать кусочки
readChunk();
});
// как только MediaSource будет оповещен , что источник готов отдавать кусочки
// видео/аудио потока
// создаем буфер , следует обратить внимание, что буфер должен знать в каком формате
// каким кодеком был закодирован поток, чтобы тем же способом прочитать видеопоток
mediaSource.addEventListener('sourceopen', function() {
var mediaSource = this;
sourceBuffer = mediaSource.addSourceBuffer("video/webm; codecs="vp8"");
});
function readChunk() {
var reader = new FileReader();
reader.onload = function(e) {
// как только FileReader будет готов, и загрузит себе кусочек видеопотока
// мы "прицепляем" перекодированный в Uint8Array (был Blob) кусочек в буфер, связанный
// с проигрывателем, и проигрыватель начинает воспроизводить полученный кусочек видео/аудио
sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
reader.onload = null;
}
reader.readAsArrayBuffer(arrayOfBlobs.shift());
}
</script>
ஸ்ட்ரீமிங் சேவையின் முன்மாதிரி தயாராக உள்ளது. முக்கிய குறைபாடு என்னவென்றால், வீடியோ பிளேபேக் கடத்தும் பக்கத்தை விட 100 எம்எஸ் பின்தங்கியிருக்கும்; வீடியோ ஸ்ட்ரீமை சேவையகத்திற்கு அனுப்பும் முன் அதை நாமே அமைக்கிறோம். மேலும், எனது மடிக்கணினியை நான் சோதித்தபோது, கடத்தும் மற்றும் பெறும் பக்கங்களுக்கு இடையிலான பின்னடைவு படிப்படியாக குவிந்தது, இது தெளிவாகத் தெரிந்தது. இந்த குறைபாட்டை சமாளிப்பதற்கான வழிகளைத் தேட ஆரம்பித்தேன்
ஆதாரம்: www.habr.com