1. 아래 코드를 </head> 위에 넣는다.
youtubeVideoKey는 반드시 있어야하고(기본값 그대로 둘 것을 권장, 다른 비디오에서 가져와도 됨),
youtubePlayListKey는 유튜브 재생목록 URL에서 playlist?list= 라는 키워드 바로 뒤에 오는 걸 복사해오면 된다.
<script>
//////////////////////////////////////////////////////////////////////
// BLOG BGM With Youtube
// BY. https://d-dl.tistory.com/
//////////////////////////////////////////////////////////////////////
// [ SETTING ]
const youtubeVideoKey = "cfTLvQ9TZhg";
const youtubePlayListKey = "PLSaAi5XOwA7O1eDCn1lMZ4L1YGNZwXvvu";
const URLChange = true;
const setShuffle = true;
const volumeUpDownValue = 10; // 0~100
const config = {
'loop': 1,
'autoplay': 1,
'controls': 1,
'disablekb': 1,
'enablejsapi': 1,
'iv_load_policy': 3,
'origin': document.location.origin
};
//////////////////////////////////////////////////////////////////////
// [ BODY ]
let YTplayer = null;
window.addEventListener('DOMContentLoaded', (event) => {
console.clear();
if (parent[0].name !== '') return;
let docIframe = document.createElement("iframe");
docIframe.style.cssText = `width: 100vw; height: 100vh; overflow: auto; border: 0; margin: 0; position: absolute;`;
docIframe.name = "MAIN";
docIframe.id = "BGM_DOC_IFRAME";
docIframe.src = document.location;
docIframe.addEventListener("load", function(e) {
const iframePath = docIframe.contentDocument.location.pathname;
if (URLChange && document.location.pathname !== iframePath){
history.replaceState(null, null, iframePath);
}
});
let musicDiv = document.createElement("div");
musicDiv.name = "MUSIC";
musicDiv.id = "Youtube_Music_Iframe";
document.body.style.overflow = "hidden";
document.body.innerHTML = "";
document.body.prepend(docIframe);
document.body.prepend(musicDiv);
let tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
function onYouTubeIframeAPIReady() {
YTplayer = new YT.Player('Youtube_Music_Iframe', {
videoId: youtubeVideoKey,
playerVars: config,
height: '0',
width: '0',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError
}
});
}
let listSet = false;
function onPlayerReady(event) {
if (!listSet && youtubePlayListKey !== null) {
YTplayer.loadPlaylist({
list:youtubePlayListKey,
listType:'playlist',
index:0,
startSeconds:0,
suggestedQuality:'small'
});
YTplayer.setShuffle(setShuffle);
listSet = true;
}
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
if (listSet)
YTplayer.nextVideo();
else
YTplayer.playVideo();
}
}
function onPlayerError(event) {
console.error(event.data);
}
function receiveBGMMessage(event)
{
let state = event.data.BGM;
if (!state) return;
switch (state.toString().toLowerCase()) {
case 'play':
YTplayer.playVideo();
break;
case 'pause':
YTplayer.pauseVideo();
break;
case 'previous':
YTplayer.previousVideo();
YTplayer.playVideo();
break;
case 'next':
YTplayer.nextVideo();
YTplayer.playVideo();
break;
case 'volumeup':
YTplayer.setVolume(YTplayer.getVolume() + volumeUpDownValue);
break;
case 'volumedown':
YTplayer.setVolume(YTplayer.getVolume() - volumeUpDownValue);
break;
}
console.log(`%c♬ BGM : NOW "${state.toUpperCase()}"`, 'color:blue');
}
addEventListener("message", receiveBGMMessage, false);
</script>
2. BODY 태그 내부에 아래 코드를 넣어준다.
<!-- IN HTML Button -->
<button onclick="parent.postMessage({BGM:'play'}, '*')">재생</button>
<button onclick="parent.postMessage({BGM:'pause'}, '*')">정지</button>
<button onclick="parent.postMessage({BGM:'previous'}, '*')">이전</button>
<button onclick="parent.postMessage({BGM:'next'}, '*')">다음</button>
<button onclick="parent.postMessage({BGM:'volumeup'}, '*')">볼륨업</button>
<button onclick="parent.postMessage({BGM:'volumedown'}, '*')">볼륨다운</button>
3. button들을 눌러 정상 작동을 확인한다.
이 코드를 썼을 때 장점은
- Iframe을 이용한 눈속임이지만 URL이 자동으로 바뀐다.
- 추가는 안했지만 유튜브 API를 대다수 쓸 수 있을 듯.
- 블로그 내에서 페이지 이동을 하더라도 노래가 끊기지 않는다.
- 예제에선 button으로 넣었지만 저 onclick 요소만 그대로 복사하면 다른 태그에도 붙일 수 있다. 즉, 꾸미기 쉽다.
단점은
- URL 자동 바뀜이 약간 늦다.
- target="_blank"가 아닌 타 사이트로 이동하면 그대로 작동할 듯...?
- 모바일 작동 안할 듯...? (테스트X)
리액트 공부하다 문의받았던 게 생각나서 시작했는데, 몇몇 요소가 헷갈리기도 했고 자동재생 문제로 삽질하다 생각보다 오래 걸렸다.
크롬 정책 때문에 이제 BGM 자동 재생은 무조건 불가능하고, 사용자가 한 번 이상 클릭해야 작동하는 모양이다. setTimeout 같은 거로 속임수를 써보려그랬는데도 다 막혀있었다... 아쉽긴 하지만 사용자 웹 환경 개선/데이터 소비량 축소를 위해서라고 하니 반박할 거리는 없는 듯.
여기서 더 기능 추가/오류 수정을 할 수 있을진 모르겠지만 제보받으면 추가 예정.
참고 문서
https://developers.google.com/youtube/iframe_api_reference