Пришла мне однажды идея создать трансляцию с камеры, и я решил ее реализовать. Для создания этого дела нам понадобится 4 файла (5, если считать CSS).
1. Index.php. Где будет сама трансляция.
2. Save.php. Куда будет сохраняться изображение.
3. Now.php. Где будет храниться изображения в base:64.
4. Translate.php. Откуда будет вестись трансляция.
Принцип прост: на странице translate.php пользователь открывает доступ к камере, потом делается снимок каждую секунду, потом этот снимок отправляется на страницу index.php.
Приступим. Index.php. Тут ничего сложного нет.
<!doctype html>
<head>
<meta charset="utf-8">
<title>Просмотр</title>
<link rel="stylesheet" href="main.css" />
<script>
function g (id) {
return document.getElementById(id);
};
var ajax = {
init: function (method, url, query, callback) {
query = typeof query === "string" ? query : ajax._params(query);
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.send(query);
xhr.onreadystatechange = function (event) {
if (xhr.readyState === 4)
callback && callback(JSON.parse(xhr.responseText));
};
},
get: function (url, params, callback) {
ajax.init("GET", url + "?" + ajax._params(params), null, callback)
},
post: function (url, params, callback) {
ajax.init("POST", url, params, callback);
},
_params: function (params) {
if (typeof params === "string" || params == null)
return params;
var data = [], key, d = encodeURIComponent;
for (key in params)
data.push(d(key) + "=" + d(params[key]));
return data.join("&");
}
};
function setLoad () {
ajax.get("now.php", "", function (data) { //берется изображение
g("img").src = data.image;
});
};
setInterval(setLoad, 50);
</script>
</head>
<body>
<div id="title">
Трансляция с вебкамеры
</div>
<div id="viewer">
<img src="data:base64," alt="" id="img" width="640" height="480" class="img-content" /> //берется изображение и выводится
</div>
</body>
</html>
save.php. Предельно прост:
<?
$data = $_REQUEST["data"]; // получаем изображение
$fh = fopen("now.png", "w+"); // создаем и открываем файл с изображением
$save = fwrite($fh, $data); // записываем данные в него
fclose($fh); // закрываем файл
exit(json_encode(["success" => !!$save, "time" => time()]));
?>
now.php. Тоже ничего сложного:
<?
exit(json_encode(["image" => file_get_contents("./now.png")], JSON_UNESCAPED_UNICODE));
?>
translate.php. Вот тут и начинаются танцы с бубном:
<!doctype html>
<head>
<meta charset="utf-8">
<title>Трансляция</title>
<link rel="stylesheet" href="main.css" />
<script>
function g (id) {
return document.getElementById(id);
};
var ajax = {
init: function (method, url, query, callback) {
query = typeof query === "string" ? query : ajax._params(query);
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(query);
xhr.onreadystatechange = function (event) {
if (xhr.readyState === 4)
callback && callback(JSON.parse(xhr.responseText));
};
},
get: function (url, params, callback) {
ajax.init("GET", url + "?" + ajax._params(params), null, callback)
},
post: function (url, params, callback) {
ajax.init("POST", url, params, callback);
},
_params: function (params) {
if (typeof params === "string" || params == null)
return params;
var data = [], key, d = encodeURIComponent;
for (key in params)
data.push(d(key) + "=" + d(params[key]));
return data.join("&");
}
};
Number.prototype.n2 = function () {
return this < 10 ? "0" + this : this;
};
Date.prototype.getString = function () {
return [
this.getDate(),
".",
(this.getMonth() + 1).n2(),
".",
this.getFullYear(),
" ",
this.getHours(),
":",
this.getMinutes().n2(),
":",
this.getSeconds().n2()
].join("");
};
var Media = {
media: navigator.getUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia,
url: window.URL.createObjectURL || window.URL.msCreateObjectURL || window.URL.mozCreateObjectURL || window.URL.webkitCreateObjectURL,
video: null,
canvas: null,
ctx: null,
init: function (video, canvas) {
if (!Media.media || !Media.url)
return alert("Не поддерживается Вашим браузером!");
Media.canvas = canvas;
Media.ctx = canvas.getContext("2d");
Media.video = video;
Media.media.call(navigator, {video: true}, Media.onSuccess, Media.onError);
},
onSuccess: function (stream) {
var stream = Media.url(stream);
Media.video.src = stream;
Media.video.play();
setTimeout(function () {
Media.save(Media.getImage());
}, 4000);
},
getImage: function () {
Media.canvas.width = Media.canvas.width;
Media.ctx.drawImage(Media.video, 0, 0, Media.canvas.width, Media.canvas.height);
Media.ctx.font = "22px Tahoma";
var date = new Date().getString();
Media.ctx.fillStyle = "white";
Media.ctx.fillText(date, 9, Media.canvas.height - 16);
Media.ctx.fillStyle = "black";
Media.ctx.fillText(date, 10, Media.canvas.height - 15);
return Media.canvas.toDataURL("image/jpeg", .9);
},
save: function (data) {
ajax.post("save.php", {
data: data
}, function (data) {
Media.save(Media.getImage());
if (data.success)
g("time").innerHTML = "Время: " + (new Date(data.time * 1000).toLocaleString());
});
},
onError: function(error) {
alert("Видеокамера недоступна");
}
};
window.onload = function (event) {
Media.init(g("video"), g("canvas"));
};
</script>
</head>
<body>
<div class="wrap">
<div class="side fl">
<h2>Веб-камера</h2>
<div class="img-wrapper"><video id="video"></video></div>
</div>
<div class="side fr">
<h2>Кадр на сайте</h2>
<div class="img-wrapper"><canvas id="canvas" width="480" height="360"></canvas></div>
<p id="time"></p>
</div>
</div>
</body>
На этом серверная часть готова. Можно теперь добавить чуть-чуть CSS.
body{
background-color: beige;
font-family: ubuntu;
}
/* Шрифт измените на свой, если он у вас есть */
@font-face {
font-family: Ubuntu;
src: url("../Ubuntu.ttf") format("opentype");
}
#title{
text-align: center;
font-size: 30px;
}
#viewer{
text-align: center;
margin-top: 3%;
}
#viewer img{
box-shadow: 0 0 50px rgba(0,0,0,5);
}
Ну, вроде бы все. Теперь вы можете делать трансляцию с веб-камеры на сайт.