1:1 영상통화 기능을 확장시켜 영상채팅 시스템을 나름 구현해봤다. 코드는 voww project 에서 많은부분 가져다 썼다.


개발환경: 브라우저는 크롬, 리눅스 서버에 Node.js를 설치 (설치관련 내용은 이전 포스팅 참고)


개발도구: 디버깅 - 크롬, 소스편집 툴 - Notepad++(FTP 기능을 이용)


브라우저(크롬)에서 거의 모든 기능을 지원해주다보니 구현할 내용이 별로 없었다. 


자잘한 에러들이 남았겠지만 주기능 구현 후 귀찮... -_-;


주요기능


로그인, 방 만들기, 영상채팅 참가하기, 방에서 뛰쳐나오기, 로그아웃


Front-end 







Back-end




공통



테스트

 

Front-end 코드가 있는 쪽에서, 웹서버 돌리기

shell> python -m SimpleHTTPServer 8888


Back-end 코드가 있는 쪽에서, 웹소켓 서버 돌리기

shell> node webconf.js


브라우저를 열고 웹서버 주소로 들어가서 테스트 해보면 된다. 


혼자놀기 화면

 

 






Posted by DevMoon
,

HTML5에는 WebRTC라는 기술이 포함되어있다.


웹에서 실시간 커뮤니케이션을 지원한다는 뜻이다 +_+


이미 구글 크롬에는 이 기능이 들어가있다. 실시간 영상채팅을 구현하려고 찾아보니 


자료가 있긴 했는데 딱 내가 필요한만큼만 구현되어 있는 것은 찾지못했다. 


내가 찾기 원하는 것? HTML5 기술만 이용해서(다른 3rd party 코드 없이!!) 1:1 화상통화를 구현해보는 것.


일단 이게 되야 여기에 채팅을 붙이든, 더 많은 클라이언트를 붙이든 확장해볼 수 있을 것이다.


본 포스팅은 여기에 있는 코드를 참고/수정 했음을 밝히는 바이다.



Prerequisite


클라이언트: 웹브라우저 = 구글크롬, 노트북에 카메라와 마이크가 달려있다.


서버: Node.js 설치. 웹서버와 WebSocket 통신을 처리하기 위한 프로세스가 동작하고 있음.(아래 코드 참고)


다음과 같이 chrome 옵션에서 WebRTC 기능을 사용해야 한다.





HTML5 관련 객체


화상통화를 구현하기 위해서는 3가지 객체(?)에 대해 알아야 한다. 다음은 화상통화에서의 각 객체의 기능이다.

(자세한 사용법은 하단의 코드를 참고)


1. webkitGetUserMedia

- 사용자 카메라와 마이크를 이용하기 위해서 사용한다.


2. webkitDeprecatedPeerConnection 또는 webkitPeerConnection

- media(카메라, 마이크) 관련 정보와 데이터를 교환하는데 사용한다.


3. WebSocket

- 서버쪽으로 통신에 필요한 정보를 송신해서 다른 client와 연결을 맺기 위한 통로로 사용한다.

- 채팅기능을 추가한다면 이 통로를 통해 채팅 메시지가 송수신 될 것이다.



테스트 환경 구성도


테스트 환경 구성은 그림과 같다. 동작과정은 크게 2가지로 나뉜다.



처음에는 통신에 필요한 정보를 교환하는 과정인데 여기에 SDP(Session Description Protocol)가 사용된다.


쉽게 말해서 내가 보내려고 하는 정보는 영상이랑 음성이고, 위치는 어디고.. 하는 정보를 교환한다는 말이다.


이 과정이 끝나면 양쪽 클라이언트의 브라우저간에 통신 채널이 열리고 둘이 알아서 영상/음성 데이터를 주고받는다.


물론! 이 과정에서 개발자가 해줘야 할일은 아주 적은 부분에 불과하다. 하지만 짐작했다시피 서버에는 릴레이 기능이 


포함되어있어야 한다. 처음에 클라이언트들은 서버와 WebSocket을 이용해서 채널을 열어놓는다.


한쪽에서 통화요청을 하면 열어둔 채널을 통해 요청 메시지를 전송하고, 서버는 이 메시지를 다른 클라이언트에게 전달한다.


요청 메시지(SDP)를 받은 클라이언트는 이에 대해 응답하고, 자신의 정보도 보내준다. 그럼 최초에 통화요청한 클라이언트는


이 메시지를 받은 후 응답하고 드디어 통화가 시작된다. SDP 메시지는 크롬에서 알아서 만들어주므로 


우리가 할일은 WebSocket을 이용해서 데이터를 서버로 보내는일과 적절한 타이밍에 미디어 정보를 붙이는(?)일 뿐이다.



코드


백문이 불여일견이라. 


Back-end script(broadcast.js)

#!/usr/bin/env node

var WebSocketServer = require('websocket').server;
var http = require('http');

var clients = [];
var idlist = [];
var id = 0;

var server = http.createServer(function(request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
});
server.listen(8080, function() {
    console.log((new Date()) + ' Server is listening on port 8080');
});

wsServer = new WebSocketServer({
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
  // put logic here to detect whether the specified origin is allowed.
  return true;
}

wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
      // Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }

    var connection = request.accept(null, request.origin);

    clients.push(connection);
    idlist.push(request.key);

    console.log((new Date()) + ' Connection accepted.');

    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);

            for(var i = 0; i < idlist.length; i++) {
                if (idlist[i] != request.key) {
                    cli = clients[i];
                    msg = message.utf8Data;
                    cli.sendUTF(msg);
                }
            }
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
            connection.sendBytes(message.binaryData);
        }
    });

    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});



Front-end script(webconf.html)

<!DOCTYPE html>
<html>
<head>

<script type="text/javascript">
  	var localVideo;
  	var remoteVideo;
  	var localStream;
  	var pc = null;
	var wsock;
	var remoteSrc = null;

  	var STUN_CONF = "NONE";

	// 초기화 함수. 연결요청, 연결수신 client 공통.
	initialize = function() {
    	console.log("Initializing");
		
    	localVideo = document.getElementById("localVideo");
    	remoteVideo = document.getElementById("remoteVideo");

    	resetStatus();
    	// 카메라, 마이크 열기
		getUserMedia();
		// server와 websocket을 열어둔다.
		openChannel();
		
		// 연결요청 버튼 click시 SDP정보 교환 시작
		document.getElementById("join").onclick = function() {
			rtcStart();
		}
  	}

  	resetStatus = function() {
    	setStatus("Initializing...");
  	}

	function openChannel() {
		// SDP 정보 교환을 위해, 서버와 연결한다.
    	url = "ws://192.168.25.114:8080";
	    wsock = new WebSocket(url);

    	wsock.onopen = function() {
        	console.log("open");
    	}
		
		// 서버로부터 메시지를 받을 때 처리.
    	wsock.onmessage = function(e) {
			console.log("S->C:");
        	console.log(e.data);

			// 연결 요청을 받는 client를 위한 코드. 수신측 client는 일단 메시지를 받아야 한다.
			// peerConnection 객체를 생성하고 자신의 media stream을 연결한다.
			if (pc == null) {
				createPeerConnection();
      			pc.addStream(localStream);
			}
				
			// SDP message는 아래 함수로 넘겨주면 된다. 응답은 알아서 해주므로..
        	pc.processSignalingMessage(e.data);
    	}

    	wsock.onclose = function(e) {
        	console.log("closed");
    	}
	}
	
	// 카메라, 마이크 자원을 얻는다.
  	getUserMedia = function() {
    	try {
      		navigator.webkitGetUserMedia({audio:true, video:true}, onUserMediaSuccess,
                                   onUserMediaError);
      		console.log("Requested access to local media with new syntax.");
    	} catch (e) {
      		try {
        		navigator.webkitGetUserMedia("video,audio", onUserMediaSuccess,
                		                     onUserMediaError);
        		console.log("Requested access to local media with old syntax.");
      		} catch (e) {
        		alert("webkitGetUserMedia() failed. Is the MediaStream flag enabled in about:flags?");
        		console.log("webkitGetUserMedia failed with exception: " + e.message);
      		}
    	}
  	}

	// peerConnection 생성
  	createPeerConnection = function() {
    	try {
			// STUN서버 주소와 SDP 메시지를 보내는 함수를 넣어준다.
      		pc = new webkitDeprecatedPeerConnection(STUN_CONF,
                                              onSignalingMessage);
      		console.log("Created webkitDeprecatedPeerConnnection with config");
    	} catch (e) {
      		console.log("Failed to create webkitDeprecatedPeerConnection, exception: " + e.message);
      		try {
        		pc = new webkitPeerConnection(STUN_CONF,
                                      onSignalingMessage);
        		console.log("Created webkitPeerConnnection with config.");
      		} catch (e) {
        		console.log("Failed to create webkitPeerConnection, exception: " + e.message);
        		alert("Cannot create PeerConnection object; Is the 'PeerConnection' flag enabled in about:flags?");
        		return;
      		}
    	}

    	pc.onconnecting = onSessionConnecting;
    	pc.onopen = onSessionOpened;
    	pc.onaddstream = onRemoteStreamAdded;
    	pc.onremovestream = onRemoteStreamRemoved;
  	}

	// 연결을 요청하는 client를 위한 함수
	// join 버튼을 누르면 동작한다.
	rtcStart = function() {

    	setStatus("Connecting...");
      	console.log("Creating PeerConnection.");
      	createPeerConnection();

      	console.log("Adding local stream.");
		
		// 자신의 media를 연결시킨다. peerConnection을 생성한 이후에 반드시 해줄 것.
      	pc.addStream(localStream);
	}

  	setStatus = function(state) {
    	footer.innerHTML = state;
  	}
	
	// media관련 함수들
	
  	onUserMediaSuccess = function(stream) {
    	console.log("User has granted access to local media.");
    	var url = webkitURL.createObjectURL(stream);
    	localVideo.style.opacity = 1;
    	localVideo.src = url;
    	localStream = stream;
  	}

  	onUserMediaError = function(error) {
    	console.log("Failed to get access to local media. Error code was " + error.code);
    	alert("Failed to get access to local media. Error code was " + error.code + ".");
  	}

	// signaling 관련함수들
	
  	onSignalingMessage = function(message) {
   		console.log('C->S: ' + message);
		// 열어둔 websocket으로 SDP 메시지를 전송한다.
		// peerConnection을 생성하자마자 바로 SDP 메시지를 보낸다.
		wsock.send(message);	
  	}

  	onSessionConnecting = function(message) {
    	console.log("Session connecting.");
  	}

  	onSessionOpened = function(message) {
   		console.log("Session opened.");
  	}

  	onRemoteStreamAdded = function(event) {
    	console.log("Remote stream added.");
    	var url = webkitURL.createObjectURL(event.stream);
    	remoteVideo.style.opacity = 1;
    	remoteVideo.src = url;
		remoteSrc = url;
    	setStatus("<input type=\"button\" id=\"hangup\" value=\"Hang up\" onclick=\"onHangup()\" />");
  	}

  	onRemoteStreamRemoved = function(event) {
    	console.log("Remote stream removed.");
  	}

  	onHangup = function() {
    	console.log("Hanging up.");
    	localVideo.style.opacity = 0;
    	remoteVideo.style.opacity = 0;
    	pc.close();
    	pc = null;
    	setStatus("You have left the call.");
  	}

</script>
</head>

<body onload="initialize();">
<div id="container">

  <div id="local">
    <video
     width="25%" height="25%" id="localVideo" autoplay="autoplay" style="opacity: 0;
     -webkit-transition-property: opacity;
     -webkit-transition-duration: 2s;">
    </video>
  </div>

  <div id="remote">
    <video width="25%" height="25%" id="remoteVideo" autoplay="autoplay"
     style="opacity: 0;
     -webkit-transition-property: opacity;
     -webkit-transition-duration: 2s;">
    </video>
  </div>

  <div id="footer"></div>

</div>

<button id="join">join</button>
</body>
</html>





테스트


서버쪽에서 해줘야 할 일. 미리 설치할 것은 링크걸린 포스팅 참고.


1. webserver 돌리기. front-end script가 있는 곳에서 다음명령 수행


shell> python -m SimpleHTTPServer 8888


2. WebSocket server 돌리기. back-end script가 있는 곳에서 다음명령 수행


shell> node broadcast.js


이제 크롬을 열고 웹서버에 접속하면 된다. 2개의 브라우저에서 서버에 접속해있도록 한다.


(주의 할 것은 지금 구현해 놓은 것이 딱 1:1만 되도록 해놨기 때문에 2명 이상이 접속하면 안되요!! 나는 꼼수다...)


카메라를 사용할꺼냐고 물어보면 당근 사용한다고 하자. 이제 자신의 얼굴이 보인다.


두 개의 브라우저 중 하나에서 하단에 보이는 join 버튼을 누른다. 그럼 상대방 얼굴도 보인다. 다음은 혼자놀기 인증샷.


(자신의 얼굴이 두 개라 썩 유쾌하지는 않지만 ..)





F12 버튼을 누르면 하단에 보이는, 주고받은 SDP 메시지를 볼 수 있다. 구글 크롬 참 좋아요.


Posted by DevMoon
,

WebSocket echo 테스트 코드를 조금만 수정하면 아주 간단한 채팅 어플을 만들 수있다. 


이런것이 모두 web에서 가능하다는 것!!


back-end script (broadcast.js)

var WebSocketServer = require('websocket').server;
var http = require('http');

var clients = [];
// 임의로 ID부여하기 위함
var idlist = [];
var id = 0;

var server = http.createServer(function(request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
});
server.listen(8080, function() {
    console.log((new Date()) + ' Server is listening on port 8080');
});

wsServer = new WebSocketServer({
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
  // put logic here to detect whether the specified origin is allowed.
  return true;
}


wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
      // Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }

    var connection = request.accept(null, request.origin);

    clients.push(connection);
    // 임의로 id값을 할당함. request.key값으로 client 구분
    idlist[request.key] = id++;

    console.log((new Date()) + ' Connection accepted.');
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
                     // 브로드캐스팅!!
            clients.forEach(function(cli) {
                msg = idlist[request.key]+ ': ' +message.utf8Data;
                cli.sendUTF(msg);
            });
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
        }
    });
    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});



front-end script (websocket.html)

<!DOCTYPE html>
<title>WebSocket Test Page</title>
<script>

    var log = function(s) {
        console.log(s);
        if (document.readyState !== "complete") {
            log.buffer.push(s);
        } else {
            document.getElementById("output").innerHTML += (s + "\n")
        }
    }
    log.buffer = [];

    url = "ws://192.168.25.114:8080";
    w = new WebSocket(url);

    w.onopen = function() {
        log("open");
        w.send("thank you for accepting this Web Socket request");
    }

    w.onmessage = function(e) {
        console.log(e.data);
        log(e.data);
    }

    w.onclose = function(e) {
        log("closed");
    }

    window.onload = function() {
        log(log.buffer.join("\n"));

        document.getElementById("sendButton").onclick = function() {
            console.log(document.getElementById("inputMessage").value);
            w.send(document.getElementById("inputMessage").value);
        }
              // 간지나게 엔터키 누르면 메시지 날림
        document.getElementById("inputMessage").onkeypress = function() {
            if (event.keyCode == '13') {
                value = document.getElementById("inputMessage").value
                w.send(value);
                document.getElementById("inputMessage").value = "";
            }
        }
    }
</script>

<input type="text" id="inputMessage">
<button id="sendButton">Send</button>
<pre id="output"></pre>



echo 예제와 마찬가지로 server 돌려주고 웹으로 접속. 끄읕!!


shell> python -m SimpleHTTPServer 8888

shell> ./node broadcast.js


웹브라우저 창을 두개 열고 접속해서 테스트해보면 된다.



Posted by DevMoon
,

양방향 통신을 지원하는 WebSocket을 이용해서 이것저것 해보려하는데 기본적인 echo 테스트부터 막혔다.


클라이언트(front-end)쪽 코드는 간단해서 구현하기 쉬웠지만 문제는 서버쪽(back-end)이었다.


내가 참고한 책(프로 HTML5 프로그래밍)에 나와있는 코드대로 해도 실행이 잘 되지않아 제대로 된 서버를 구하기로 했다.


참고로 내가 테스트한 환경은 다음과 같다.


서버 - Redhat linux 2.6.32

웹브라우저 - 구글 크롬


WebSocket server를 구동시키기 위해 Node.js를 사용한다.



Node.js 설치


Node.js는 서버측에서 사용되는 javascript 엔진이다. 일단 요놈이 필요하다.


Node.js 홈페이지에 가면 구할 수 있다. 다운로드를 클릭한 후 압축된 source code 주소를 복사해두자.


다음과 같이 서버에 다운받고 설치를 해둔다.


shell> wget http://nodejs.org/dist/v0.6.19/node-v0.6.19.tar.gz

shell> tar xvzf node-v0.6.19.tar.gz

shell> cd node-v0.6.19

shell> ./configure

shell> make

shell> make install



WebSocket 모듈설치


Node.js에는 기본적으로 WebSocket 모듈이 들어있지 않은 모양이다. 그래서 따로 설치를 해줘야 한다.


모듈 설치에는 npm(Node Package Manager)이라는 것을 사용하면 편하다.


다음과 같이 npm과 WebSocket 모듈을 설치할 수 있다. npm은 /usr/local/bin에 설치된다.


shell> curl http://npmjs.org/install.sh | sh

shell> cd /usr/local/bin

shell> ./npm install websocket



WebSocket echo Front/Back-end script


이제 필요한 준비가 모두 끝났다. 구미에 맞는 서버를 구현해서 띄워놓고 테스트를 해보자.


/usr/local/bin에 다음 파일을 만들어둔다.


ws_server.js

#!/usr/bin/env node
var WebSocketServer = require('websocket').server;
var http = require('http');

var server = http.createServer(function(request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
});
server.listen(8080, function() {
    console.log((new Date()) + ' Server is listening on port 8080');
});

wsServer = new WebSocketServer({
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
  // put logic here to detect whether the specified origin is allowed.
  return true;
}

wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
      // Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }

    var connection = request.accept(null, request.origin);
    console.log((new Date()) + ' Connection accepted.');
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF(message.utf8Data);
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
            connection.sendBytes(message.binaryData);
        }
    });
    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});


다음과 같이 Front-end script를 구현한다. (반드시 Back-end 코드와 같은 위치에 있을 필요는 없다)


websocket.html

<!DOCTYPE html>
<title>WebSocket Test Page</title>
<script>

    var log = function(s) {
        console.log(s);
        if (document.readyState !== "complete") {
            log.buffer.push(s);
        } else {
            document.getElementById("output").innerHTML += (s + "\n")
        }
    }
    log.buffer = [];
    // 아래 값은 상황에 맞게 변경할 것
    url = "ws://192.168.25.114:8080";
    w = new WebSocket(url);

    w.onopen = function() {
        log("open");
        w.send("thank you for accepting this Web Socket request");
    }

    w.onmessage = function(e) {
        console.log(e.data);
        log(e.data);
    }

    w.onclose = function(e) {
        log("closed");
    }

    window.onload = function() {
        log(log.buffer.join("\n"));
        document.getElementById("sendButton").onclick = function() {
            console.log(document.getElementById("inputMessage").value);
            w.send(document.getElementById("inputMessage").value);
        }
    }
</script>

<input type="text" id="inputMessage" value="Hello, Web Socket!"><button id="sendButton">Send</button>
<pre id="output"></pre>



코드를 보면 알 수 있듯이 Front-end 코드는 거의 해줄게 없다. 


WebSocket 객체에 onopen, onmessage, onclose callback 함수만 걸어놓고 그 안에서 필요한 처리만 해주면 된다.


테스트


Front-end 파일(websocket.html)이 있는 곳에서 다음과 같이 웹 서버를 실행한다. 


웹서버로는 python으로 구현된 SimpleHTTPServer를 이용했다. (기본설치되어 있었음. 없으면 설치해야....)


python -m SimpleHTTPServer 8888


그리고, Back-end(ws_server.js) 파일이 있는 곳에서 자신이 만든 echo 서버를 실행시킨다.


./node ws_server.js


이제 웹 브라우저를 열고 들어가보자.



위와같이 잘 되면 성공이다. :)


* 참고 URL


1. 전체적인 설명 (윈도우 기반)


2. npm소스코드가 있는곳. 유용한 명령도 있다.






Posted by DevMoon
,

HTML5에서는 위치정보를 얻어갈 수 있는 API를 제공한다. 다음은 사용예.


navigator.geolocation.getCurrentPosition(updateLocation, handleLocationError);


navigator.geolocation.watchPosition(updateLocation, handleLocationError, {maximumAge:2000});


function updateLocation(position) {

...

position에 위치관련 정보가 담겨져있다.

}


function handleLocationError(error) {

...

error에 error관련 정보가 담겨져있다.

}


updateLocation, handleLocatoiinError 는 callback 함수이며, 


위치정보를 얻어오는데 성공하면 updateLocation() 함수가, 에러가 발생하면 handleLocatoiinError() 함수가 호출된다.


getCurrentPosition() 함수가 단발성으로 위치정보를 얻어오는데 반해, 


watchPosition() 함수를 이용하면 주기적으로 위치정보를 얻어올 수 있다. maximumAge는 한마디로 갱신주기를 의미한다.


watchPosition() 함수를 사용할 때, updateLocation() callback은 위치정보가 변경된 경우에만 호출된다.


다음은 간단한 테스트 코드.



참고링크: 요기


테스트 브라우저. 둘 다 잘 된다.



 노트북iPad2



Posted by DevMoon
,

캠을 이용하는 예제가 있는데 로컬에서 하면 화면이 나오지않아서 다음과 같이 했다. (당연히 캠은 설치되어 있어야 한다)


나의 작업환경.


- 노트북을 쓴다. (웹캠이 달려있다)

- 브라우저는 chrome이다.

- 운영체제는 윈도우7이다.


1. 테스트용 서버(Linux)에서 HTTP server를 돌렸다.


python -m SimpleHTTPServer 8888


2. index.html 파일을 만들고 다음과 같이 코딩.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

    <script>

    function load() {

        var video = document.getElementById('myVideo');

        if (navigator.webkitGetUserMedia) {

navigator.webkitGetUserMedia({audio:true, video:true},

                function(stream) { video.src = webkitURL.createObjectURL(stream); },

                function(error) { alert('ERROR: ' + error.toString()); } );

        } else {

            alert('webkitGetUserMedia not supported');

        }

    }

    </script>

</head>

    <body onload="load()">

        <video width="100%" height="100%" autoplay="autoplay" id="myVideo" />

    </body>

</html>


3. 이제 브라우저로 접속(http://serverip:8888)하면 캠으로 내 모습이 보인다. 인증샷.





이렇게 간단한 코딩으로 캠을 이용할 수 있다니..


참고링크: 요기


Posted by DevMoon
,

HTML5 기술 중 하나인 WebSocket에 관심이 생겨서 이용해보았다.


jWebSocket은 java로 만든 것이고, 여기서 다운로드 받으면 된다. 


하던 중 다음과 같은 에러가 나서 짜증 ㅡ"ㅡ 


에러: client origin 'null' does not match allowed domains


확인해보니 chrome에서 origin값을 null로 셋팅하는 것같다.


서버쪽 conf 폴더에 jWebSocket.xml이라는 파일이 있다. 여기에 다음과 같이 해준다.


<!-- CAUTION! -->

<!-- not all browsers automatically accept self-signed certificates -->

<!-- please follow instructions on the jWebSocket.org website, how

     to trust self-signed certificates for the various browsers or

 how to import signed private key/certificate bundles into the keystore -->


<!-- these domains are accepted by the engine listening on the above mentioned port -->

<!-- you optionally can add asterisks as wild cards -->

<domains>

<domain>http*://jwebsocket.org</domain>

<domain>http*://jwebsocket.com</domain>

<domain>http*://*.jwebsocket.org</domain>

<domain>http*://*.jwebsocket.com</domain>

<domain>http*://10.10.*</domain>

<domain>http*://10.21.*</domain>

<domain>http*://192.168.*</domain>

<domain>http*://localhost*</domain>

<domain>*</domain>

</domains>

....


빨간색 부분이 내가 설정해준 부분이다. 이렇게 하고 서버 돌리면 끝.


client쪽 demo 폴더에 보면 여러가지 예제들이 있다.


Posted by DevMoon
,