이 글은 PC 버전 TISTORY에 최적화 되어있습니다.
서론
Cocos Creaor에서 비디오를 재생시켜보도록 하겠습니다. 영상은 각자 준비해주세요! (MP4를 권장)
컴포넌트 등록
1. 아래와 같이 Video라는 빈 노드를 만들어 놓습니다. 일단 저는 원격지 동영상을 재생시킬 것은 아니기 때문에 (원격지가 필요하다면 Resource Type을 Remote로 그리고 원격지 URL을 넣어줍시다.) 타입을 Local로 했습니다.
이제 클립 부분에 확장자가 mp4인 동영상을 드래그해줍니다. 저는 유튜브에서 창모 노래를 받아서 넣어보았습니다.
2. Video 이벤트를 관리할 Video 핸들러를 아래와 같이 만들어줍니다.
- onLoad에서는 비디오 플레이어의 이벤트를 수신할 함수를 등록해줍니다.
- handleVideoEvent에서는 수신한 이벤트에 대한 처리를 해줍니다.
const {ccclass, property, requireComponent} = cc._decorator;
@ccclass
@requireComponent(cc.VideoPlayer)
export default class VideoHandler extends cc.Component {
videoPlayer: cc.VideoPlayer = null;
onLoad() {
// 이벤트 핸들러에 이벤트 발생 시 수신할 함수 등록
this.videoPlayer = this.node.getComponent(cc.VideoPlayer);
var videoPlayerEventHandler = new cc.Component.EventHandler();
videoPlayerEventHandler.target = this.node;
videoPlayerEventHandler.component = "VideoHandler"
videoPlayerEventHandler.handler = "handleVideoEvent";
this.videoPlayer.videoPlayerEvent.push(videoPlayerEventHandler);
}
handleVideoEvent(videoPlayer, eventType, customData) {
console.log(videoPlayer, eventType, customData)
switch(eventType) {
case cc.VideoPlayer.EventType.PLAYING:
console.log('PLAYING.');
break;
case cc.VideoPlayer.EventType.STOPPED:
console.log('STOPPED.');
break;
case cc.VideoPlayer.EventType.CLICKED:
console.log('CLICKED.');
break;
case cc.VideoPlayer.EventType.COMPLETED:
console.log('COMPLETED.');
break;
case cc.VideoPlayer.EventType.META_LOADED:
console.log('META_LOADED.');
break;
case cc.VideoPlayer.EventType.READY_TO_PLAY:
console.log('READY_TO_PLAY.');
this.videoPlayer.play(); // 플레이를 직접해줘야함
break;
}
}
}
3. 주의할 점이 있다면?
- 노드 생성 시 초기 사이즈가 0, 0 이기 때문에 화면에 아무것도 보이지 않음. 동영상 사이즈 만큼 키워준다.
- VideoPlayer에 동영상 등록해도 아무것도 일어나지 않는다. 코드 상에서 play 시켜줘야함.
- 이벤트 타입을 핸들함수에서 찍어보면 숫자가 나오므로 cc.VideoPlayer.EventType으로 분기 검사해야함.
결과
아래와 같이 동영상이 잘 나오는 것을 볼 수 있습니다. 또한 콘솔로 현재 비디오 플레이어의 상태 정보를 알 수 있습니다.
IOS 이슈
위에서 다뤘던 Video 이벤트 콜백 흐름은 META_LOADED -READY_TO_PLAY입니다. READY_TO_PLAY에서 동영상 play를 시켰었죠. 하지만 IOS는 MEATA_LOADED 이후 콜백이 안 왔고, play를 실행해도 미리보기도 없는 빈 화면만 유지될 뿐이었습니다.
단순히 IOS에서는 Video Player가 지원이 안되는구나싶어 다음의 코드로 태그를 직접 만들어 붙였습니다.
@ccclass
export default class NewClass extends cc.Component {
onLoad() {
let gameDiv = document.getElementById('GameDiv');
let container = document.getElementById('Cocos2dGameContainer');
let canvas = document.getElementById('GameCanvas');
let videoContainer = document.createElement('div');
let videoPlayer = document.createElement("video");
let videoSource = document.createElement("source");
container.style.position = 'absolute';
videoContainer.id = 'videoContainer';
videoContainer.style.position = 'absolute';
videoPlayer.width = 500;
videoPlayer.height = 300;
videoSource.src = "https://www.w3schools.com/tags/mov_bbb.mp4";
videoSource.type = "video/mp4";
videoPlayer.appendChild(videoSource);
gameDiv.appendChild(videoContainer);
videoContainer.appendChild(videoPlayer);
videoPlayer.play();
}
}
<동적으로 태그를 만드는 모습>
위 코드를 실행하게 되면 다음과 같이 Chrome Developer 도구를 통해서 Cocos2dGameContainer Div와 같은 레벨에 videoContainer를 만들 수 있습니다.
이를 통해서 웹에서 확인 했을 때 Cocos의 Canvas위에 style.position을 absolute로 줬기 때문에 겹쳐서 띄울 수 있었습니다. 이제 아이폰에서 확인해보면 되겠다 생각했죠.
하지만 제 아이폰에서는 위와 같이 빈 화면만 떴습니다. 이유를 알아보니 다음과 같았습니다. IOS에서는 사용자가 비디오 재생을 선택할 수 있는 방향으로 제어를 하고 있었습니다. 즉 autoplay와 controls 속성을 video 태그에 넣어줘야 동영상이 나타나고 사용자가 선택해서 재생을 할 수 있는 것이죠. (링크)
그래서 상단 코드에 아래와 같이 두 속성을 추가해줬습니다.
let gameDiv = document.getElementById('GameDiv');
let container = document.getElementById('Cocos2dGameContainer');
let canvas = document.getElementById('GameCanvas');
let videoContainer = document.createElement('div');
let videoPlayer = document.createElement("video");
let videoSource = document.createElement("source");
container.style.position = 'absolute';
videoContainer.id = 'videoContainer';
videoContainer.style.position = 'absolute';
videoPlayer.width = 500;
videoPlayer.height = 300;
videoPlayer.autoplay = true;
videoPlayer.controls = true;
videoSource.src = "https://www.w3schools.com/tags/mov_bbb.mp4";
videoSource.type = "video/mp4";
videoPlayer.appendChild(videoSource);
gameDiv.appendChild(videoContainer);
videoContainer.appendChild(videoPlayer);
videoPlayer.play();
테스트 결과는 다음과 같았습니다. IOS에서는 autoplay와 controls 속성을 추가하여 이슈를 해결할 수 있었습니다.
|
|
<autoplay, controls 속성 X> |
<autoplay, controls 속성 O> |
자 그럼 동적으로 생성한 html 코드가 아닌 Cocos Creator의 Video Player는 어떻게 재생 버튼을 띄울 수 있을까요? 결국에는 VideoPlayer도 위에서 만들었던 동적 video 태그처럼 태그를 만드는 것이 아닐까 생각되어 한번 찾아보았습니다. 결과적으로 video 태그를 만들고 있었죠.
다음의 코드를 추가함으로서 VideoPlayer의 재생 문제도 해결할 수 있게되었습니다.
onLoad() {
// 이벤트 핸들러에 이벤트 발생 시 수신할 함수 등록
this.videoPlayer = this.node.getComponent(cc.VideoPlayer);
var videoPlayerEventHandler = new cc.Component.EventHandler();
videoPlayerEventHandler.target = this.node;
videoPlayerEventHandler.component = "VideoHandler"
videoPlayerEventHandler.handler = "handleVideoEvent";
this.videoTag = document.getElementsByClassName('cocosVideo')[0] as HTMLVideoElement;
this.videoTag.autoplay = true;
this.videoTag.autoplay = true;
this.videoTag.controls = true;
this.videoPlayer.videoPlayerEvent.push(videoPlayerEventHandler);
}
하지만 아직 불편함은 남아 있습니다. 유저가 광고 버튼을 눌러서 실행했는데도 비디오의 재생 버튼을 눌러야한다는 점이 굉장히 나쁜 사용자 경험이라고 생각해 이를 어떻게 해결해야할까 찾아보았습니다. 코드 상에서 직접 play()를 하는 것이 아닌 사용자가 능동적으로 클릭하여 호출된 onclick에서 play()하게 되면 재생이 된다는 얘기였습니다. (링크)
그래서 위와 같이 play 버튼을 우측 하단에 만들고 클릭 시 video.play()를 하게 했더니 문제가 깔끔하게 해결되었습니다. 여기까지 Cocos Creator의 VideoPlayer 컴포넌트로 모든 브라우저에서 재생하는 방법에 대해서 다뤄봤습니다. 읽어주셔서 감사합니다.