Closed vash-sa closed 3 years ago
Добрый день.
У нас нет продукта и мы не планируем его делать, это пример созданный в образовательных целях что бы показать возможность использования WebRTC на golang.
На базе данного примера вы можете создавать различные вариации в том числе и вставить видео на сайт но вы обретёте проблемы с NAT если устройство за роутером, нужно будет пробрасывать порты.
Но как технология WebRTC избыточна для таких задач. Она ориентированная на звонки браузер -> браузер.
В случаи работы с камерой я настоятельно рекомендую использовать https://github.com/deepch/RTSPtoWSMP4f если Вы не планируете смотреть видео с мобильных устройств.
Да мы можете создать скриншот, сами необходимо использовать FFmpeg из пакета vdk https://github.com/deepch/vdk/tree/master/cgo/ffmpeg сформировать annexb кадр из sps + pps + iframe через разделитель. Но это приведёт к тому что нужно будет использовать CGO что негативно влияет на компиляцию.
Самым лучшим решение будет дёргать скрин /dev/video или если вы используете ip камеру дергать метод получения скриншота для разных камер url разный например для Dahua
http://
Вы можете написать простой get запрос и получать кадр на прямую с dev или http или можете делать скрин с video в браузере.
Мы поможем с кодом для вставки но делать скрин в в данном примере избыточно многие используют его в других целях а CGO усложнит компиляцию. Возможно мы создадим репозитарий с примером позднее.
Спасибо. Скиншоты, правда, можно брать с камер непосредственно. Помогите вот с этим, пожалуйста, "Мы поможем с кодом для вставки". Очень сильно на вас надеюсь
"В случаи работы с камерой я настоятельно рекомендую использовать https://github.com/deepch/RTSPtoWSMP4f " Здесь я понимаю та же ситуация. Http сервер слушает порт. В случае запроса по этому порту, пользователь перенаправляется на ваш templates/index.tmpl, который и воспроизводит видео на своей странице. Вставить видео у себя здесь также не получится.
В данном случае сервер - забирает поток с камеры и отдает его в браузер в app.js содержится пример плеера этот плеер можно вставить на любую страницу и указать ему откуда получать данные, по умолчанию обмен SDP для установления связи между сервером и браузером происходит по адресу http://localhost:8083/stream/receiver/H264_PCMALAW если вы хотите получать видео с любого места а не только с локального компьютера то необходимо что бы ваш сервер имел внешний ip и порт 8083 был доступен извне
Не понял. Я брал app.js + jquery-3.4.1.min.js. Закидывал в папку с сайтом.
<!DOCTYPE html>
Что у меня не так, подскажите? Плэйр загружается, в консоли [GIN] 2021/02/09 - 11:11:48 | 200 | 4.933526ms | 192.168.1.121 | GET "/stream/player/H264_PCMALAW" и на этом все.
Если указываю http://192.168.1.58:8083/stream/receiver/H264_PCMALAW то в консоли: [GIN] 2021/02/09 - 11:18:33 | 404 | 4.625µs | 192.168.1.121 | GET "/stream/receiver/H264_PCMALAW"
Мне бы хотя бы с локального получить что-нибудь.
Если набрать в браузере http://192.168.1.58:8083, то в консоли: [GIN] 2021/02/09 - 11:22:21 | 200 | 442.234µs | 192.168.1.121 | GET "/stream/codec/H264_PCMALAW" [GIN] 2021/02/09 - 11:22:21 | 200 | 85.871983ms | 192.168.1.121 | POST "/stream/receiver/H264_PCMALAW"
и видео пошло
укажите место H264_PCMALAW ваше имя потока из конфига
в данном случае видео играется не из тега
function getCodecInfo() {
$.get("../codec/" + suuid, function(data) {
.......................................................................
function getRemoteSdp() {
$.post("../receiver/"+ suuid, {
на
function getCodecInfo() {
$.get("http://192.168.1.58:8083/stream/codec/" + suuid, function(data) {
.......................................................................
function getRemoteSdp() {
$.post("http://192.168.1.58:8083/stream/receiver/"+ suuid, {
все вставил ` <!DOCTYPE html>
` Результат:
[GIN] 2021/02/09 - 11:49:35 | 404 | 5.209µs | 192.168.1.121 | GET "/stream/receiver/H264_PCMALAW" [GIN] 2021/02/09 - 11:49:35 | 200 | 26.666µs | 192.168.1.121 | GET "/stream/codec/undefined" 2021/02/09 11:49:35 Stream Not Found [GIN] 2021/02/09 - 11:49:35 | 200 | 706.06µs | 192.168.1.121 | POST "/stream/receiver/undefined"
не видит потока
Отслеживается у вас 4 адреса: router.GET("/", HTTPAPIServerIndex) router.GET("/stream/player/:uuid", HTTPAPIServerStreamPlayer) router.POST("/stream/receiver/:uuid", HTTPAPIServerStreamWebRTC) router.GET("/stream/codec/:uuid", HTTPAPIServerStreamCodec)
и здесь нет router.GET("/stream/receiver/:uuid", HTTPAPIServerStreamWebRTC) поэтому ошибка 404
Добавил в http.go router.GET("/stream/receiver/:uuid", HTTPAPIServerStreamWebRTC) Скомпилировал, результат: [GIN-debug] Listening and serving HTTP on :8083 [GIN] 2021/02/09 - 12:07:36 | 200 | 30.04µs | 192.168.1.121 | GET "/stream/codec/undefined" 2021/02/09 12:07:36 Stream Not Found [GIN] 2021/02/09 - 12:07:36 | 200 | 141.535µs | 192.168.1.121 | GET "/stream/receiver/H264_PCMALAW" 2021/02/09 12:07:36 Stream Not Found [GIN] 2021/02/09 - 12:07:36 | 200 | 667.134µs | 192.168.1.121 | POST "/stream/receiver/undefined"
Как найти поток? Что обидно, что он там есть((
<source src="http://192.168.1.58:8083/stream/receiver/H264_PCMALAW"/>
это не надо указывать браузер пытается получить это напрямую и получается ошибка
[GIN] 2021/02/09 - 11:49:35 | 404 | 5.209µs | 192.168.1.121 | GET "/stream/receiver/H264_PCMALAW"
далее
[GIN] 2021/02/09 - 11:49:35 | 200 | 26.666µs | 192.168.1.121 | GET "/stream/codec/undefined"
undefined - потому что suuid - это динамический параметр имя потока из конфигурации этот параметр получает данные в app.js
let suuid = $('#suuid').val();
добавьте в HTML
<input type="hidden" name="suuid" id="suuid" value="H264_PCMALAW">
если конечно в кофигурации есть поток с именем H264_PCMALAW
Исправил ` <!DOCTYPE html>
` Результат: 2021/02/09 12:17:26 Stream Try Connect H264_PCMALAW [GIN] 2021/02/09 - 12:17:27 | 200 | 954.795237ms | 192.168.1.121 | GET "/stream/codec/H264_PCMALAW" [GIN] 2021/02/09 - 12:17:27 | 200 | 82.030328ms | 192.168.1.121 | POST "/stream/receiver/H264_PCMALAW" [GIN] 2021/02/09 - 12:17:42 | 200 | 164.244µs | 192.168.1.121 | GET "/stream/codec/H264_PCMALAW" [GIN] 2021/02/09 - 12:17:42 | 200 | 74.96116ms | 192.168.1.121 | POST "/stream/receiver/H264_PCMALAW" 2021/02/09 12:17:47 Client Not Send ACK (probably the browser is minimized) or tab not active Close client 2021/02/09 12:17:47 WritePacket WebRTC Client Offline 2021/02/09 12:18:02 Client Not Send ACK (probably the browser is minimized) or tab not active Close client 2021/02/09 12:18:02 Stream Not Send Video Close 2021/02/09 12:18:02 WritePacket WebRTC Client Offline
{ "server": { "http_port": ":8083" }, "streams": { "H264_PCMALAW": { "on_demand": true, "url": "rtsp://....../Streaming/Channels/101" }
} } Вот config.json
"В случаи работы с камерой я настоятельно рекомендую использовать https://github.com/deepch/RTSPtoWSMP4f если Вы не планируете смотреть видео с мобильных устройств." В этом не работает, не открываются ни примеры, ни видео
Простите но не открывается слишком обширный диагноз и вопрос нужно задавать в репозитории проекта, нужно более детальное описание. Версия ОС Браузер скриншот консоли и консоли браузера. Попробуйте открыть в chrome
Я именно в chrome. Я хотел бы закончить начатое обсуждение в этом проекте.
2021/02/09 12:17:47 Client Not Send ACK (probably the browser is minimized) or tab not active Close client 2021/02/09 12:17:47 WritePacket WebRTC Client Offline 2021/02/09 12:18:02 Client Not Send ACK (probably the browser is minimized) or tab not active Close client 2021/02/09 12:18:02 Stream Not Send Video Close 2021/02/09 12:18:02 WritePacket WebRTC Client Offline
Откуда идут эти сообщения? Кто их генерирует и почему? Возможно это позволит завершить начатое обсуждение.
https://github.com/deepch/RTSPtoWebRTC/commit/b6855335a897c1ab3d3fbc91dfb46dd700f17827 обновите код и попробуйте запустить еще раз https://github.com/deepch/RTSPtoWebRTC/issues/72#issuecomment-775897243
Перекомпилировал, перезагружал, что я только не делал. Результат тот же
вот полностью рабочий пример для сервера запущенного по адресу 192.168.1.58, если запускается на том же компьютере то адрес должен быть 127.0.0.1
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="//code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/adapterjs/0.15.5/adapter.min.js"></script>
<title>demo</title>
</head>
<body>
<input type="hidden" name="suuid" id="suuid" value="H264_PCMALAW">
<div id="remoteVideos">
<video id="videoElem" autoplay muted controls></video>
</div>
</body>
<script>
let server='192.168.1.58';
let stream = new MediaStream();
let suuid = $('#suuid').val();
let config = {
iceServers: [{
urls: ["stun:stun.l.google.com:19302"]
}]
};
const pc = new RTCPeerConnection(config);
pc.onnegotiationneeded = handleNegotiationNeededEvent;
let log = msg => {
//document.getElementById('div').innerHTML += msg + '<br>'
}
pc.ontrack = function(event) {
stream.addTrack(event.track);
videoElem.srcObject = stream;
log(event.streams.length + ' track is delivered')
}
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
async function handleNegotiationNeededEvent() {
let offer = await pc.createOffer();
await pc.setLocalDescription(offer);
getRemoteSdp();
}
$(document).ready(function() {
getCodecInfo();
});
function getCodecInfo() {
$.get("//"+server+":8083/stream/codec/" + suuid, function(data) {
try {
data = JSON.parse(data);
} catch (e) {
console.log(e);
} finally {
$.each(data,function(index,value){
pc.addTransceiver(value.Type, {
'direction': 'sendrecv'
})
})
//send ping becouse PION not handle RTCSessionDescription.close()
sendChannel = pc.createDataChannel('foo');
sendChannel.onclose = () => console.log('sendChannel has closed');
sendChannel.onopen = () => {
console.log('sendChannel has opened');
sendChannel.send('ping');
setInterval(() => {
sendChannel.send('ping');
}, 1000)
}
sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}' payload '${e.data}'`);
}
});
}
let sendChannel = null;
function getRemoteSdp() {
$.post("//"+server+":8083/stream/receiver/"+ suuid, {
suuid: suuid,
data: btoa(pc.localDescription.sdp)
}, function(data) {
try {
pc.setRemoteDescription(new RTCSessionDescription({
type: 'answer',
sdp: atob(data)
}))
} catch (e) {
console.warn(e);
}
});
}
</script>
</html>
Просто шикарно!!!! Все получилось!!!
Спасибо огромное!!!
Добрый день! Вчера так все хорошо получилось в локальной сети. Решил сегодня испробовать во внешней. Пробросил все порты. Источник сигнала тот же. Выдает следующий результат:
[GIN-debug] Listening and serving HTTP on :8083 2021/02/10 12:28:56 Stream Try Connect H264_PCMALAW [GIN] 2021/02/10 - 12:28:56 | 200 | 151.66937ms | 212.3.142.215 | GET "/stream/codec/H264_PCMALAW" [GIN] 2021/02/10 - 12:28:56 | 200 | 99.237061ms | 212.3.142.215 | POST "/stream/receiver/H264_PCMALAW" 2021/02/10 12:29:16 Client Not Send ACK (probably the browser is minimized) or tab not active Close client 2021/02/10 12:29:16 Stream Not Send Video Close 2021/02/10 12:29:16 WritePacket WebRTC Client Offline
в консоли браузера что написано?
ругается на этот код
let log = msg => {
document.getElementById('div').innerHTML += msg + '
'
}
app.js:17 Uncaught TypeError: Cannot read property 'innerHTML' of null at log (app.js:17) at RTCPeerConnection.pc.ontrack (app.js:23) log @ app.js:17 pc.ontrack @ app.js:23
вы все udp порты прокинули?
Попробуйте DMZ
Или указать range портов udp и прокинуть их на роутере.
"server": {
"http_port": ":8083",
"ice_servers": ["stun:stun.l.google.com:19302"],
"webrtc_port_min": 60000,
"webrtc_port_max" 60005
},
"webrtc_port_min": 60000,
"webrtc_port_max" 60005
Это эти порты UDP?
да
я вчера скинул рабочий код без использования app.js вы судя по ошибкам в консоли at log (app.js:17) используете свой вариант
К сожалению, он у меня так работает
Смотрите - раздел issue служит для сообщениях о проблемах в нашем коде вы же пытаетесь узнать у нас об ошибках в вашем коде причем эти ошибки очень просто гуглятся и исправляются например Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https в вашем случае не работает из-за того что страница содержит запросы на другие сервера, которые возможны только через протоколы http, data, chrome, chrome-extension, https ваш же файл запускается по протоколом file:// запустите файл через протокол http и он будет работать
Да, действительно, начал работать. Прошу прошения, спасибо за подсказку. Я включил RTSPClient, err := rtspv2.Dial(rtspv2.RTSPClientOptions{URL: url, DisableAudio: true, DialTimeout: 3 time.Second, ReadWriteTimeout: 3 time.Second, Debug: true} в stream.go Выдает такие сообщения 2021/02/10 16:14:17 [Unsupported NAL Type 6] 2021/02/10 16:14:18 [Unsupported NAL Type 6] 2021/02/10 16:14:20 [Unsupported NAL Type 6]
Вы включили отладку и видите сообщения отладки. В чём ваш вопрос?
Видеомодуль работает аналогично как в локальной, так и во внешней сети. Видны перезапуски сессий и там, и там. Значит видео воспроизводится. Вопрос: почему не отображается в браузере? UDP порты пробросил.
убедитесь что настроили STUN и на странице JS и в конфиге сервера. убедитесь что прокинули порты udp.
в случаи если это не поможет обратитесь к разработчику библиотеки WebRTC https://github.com/pion/webrtc
если у вас локально всё работает по вашим совам а за роутером не работает, логично предположить что вы допустили ошибки настройки работы WebRTC за роутером почитайте про STUN сервера, учитывая что везде оборудование разное мы не как вам не можем помочь настроить вашу локальную сесть.
Спасибо. Попробую разобраться сам.
Я нашел свою ошибку. Я вместо UDP пробросил TCP порты. Исправил и все заработало
Я испытал ваш продукт на orangepi pc +. Все получилось! Но у меня проблема. Я не понимаю как вставить видео на свой сайт. У меня там много дополнительной информации и вставлять видео как гиперссылку не хочется. Я профан в golang. Может вы подскажите, как вставить видео, используя ваш http сервер, в тег
И можно ли сделать опцию для получения скриншотов видео. Т.е. фото (кадры) в определенные момент времени, по какой-нибудь внешней команде.