내 블로그에 음악을 넣어보자 - SCM Music Player

블로그에 음악을 넣어볼까?

본 블로그의 하단에는 SCM Music Player라는 음원 서비스가 탑재되어 있다. 대략 이렇게 생긴게 브라우저 하단에 위치해 있다. (아래는 캡쳐한 그림이다.)

SCM Music Player

처음엔 단순히 블로그에서 “싸이월드 때처럼 내가 듣고 싶은 음악들을 플레이해볼까?” 정도로 시작했는데, 검색해보니 SCM Music Player라는 오픈소스가 존재했다.

▶ SCM Music Player의 공식 홈페이지 - https://www.scmplayer.net/
▶ SCM Music Player의 Github 페이지 - https://github.com/cshum/scm-music-player

Github에 가면 제작자가 API를 공개해 두었으니 변형해서 쓰실 분들은 변경해서 사용하시면 된다.

SCM Music Player는 Youtube, SoundCloud 혹은 어딘가에 업로드되어 있는 MP3의 링크를 이용해서 블로그에서 스트리밍할 수 있도록 해 주는 JavaScript로 만든 도구다. 누구든지 본인이 블로그의 소스코드를 수정할 수 있다면 자신의 블로그에 스트리밍 음원 목록을 만들어 둘 수 있다. (필자의 경우는 Youtube로 구성했다.)

참고로 PC용 웹브라우저에서만 사용할 수 있으며 모바일 디바이스에서는 제공되지 않는다.

SCM Music Player의 UI는 아래와 같이 구성되어 있다.

SCM Music Player

구분
설명
플레이 컨트롤 음원의 실행, 중단, 이전 곡으로 가기, 다음 곡으로 가기 등을 할 수 있다.
음원 제목 표시 현재 진행 중인 음원의 제목이 표시되며,
제목을 클릭하면 Youtube의 해당 음원 페이지로 이동한다.
플레이 진행 표시 음원이 진행 중인 상태를 바(bar) 형태로 표시하며,
바의 위치를 옮기면 음원의 플레이 위치를 변경할 수 있다.
SCM Music Player 링크 이 음원 실행기의 이름을 표시함과 동시에 클릭 시 홈페이지로 이동하는 링크를 제공한다.
음원 진행 상태 표시 숫자로 음원의 진행 상태를 표시한다.
볼륨 조정기 음원 실행기의 볼륨을 조정할 수 있다.
목록 표시 토글 버튼 음원 전체 목록을 표시하거나, 표시를 끌 수 있다.

나만의 음원 실행기를 만들어보자

  1. 먼저 SCM Music Player의 공식 웹사이트로 이동한다.

  2. 2021년 기준 공식 홈페이지에 들어가면 아래와 같은 ‘선택 화면’이 나타나는데, 구성은 아래와 같다.

SCM Music Player

  1. 먼저 ①스킨 선택은 그냥 색상과 모양의 선택일 뿐, 사용할 때 기능에는 아무런 차이가 없으니 아무거나 선택하시면 된다.

  2. 다음은 ②음원 편집이다. 음원 편집은 플레이할 목록을 구성하는 곳으로, 「제목」을 표시하는 란과 「실제 플레이될 음원의 URI」를 입력하는 란이 있다.

SCM Music Player

  1. 실제 플레이될 음원의 URI 중 대표적인 예는 바로 유투브의 ‘공유’ 버튼을 누르면 나오는 ‘줄인 주소’가 될 수 있다. 실제 필자의 블로그에 적용된 SCM Music Player 음원은 모두 이런 식으로 만들어 졌다.

SCM Music Player
SCM Music Player

  1. 일단 음원 하나만 입력하고 다음으로 넘어가자.

SCM Music Player

  1. 다음은 ③플레이어 속성 설정 화면이다. 여기에서는 음원 플레이어의 세부 설정을 할 수 있다.

    구분 설명
    Auto Play 페이지가 켜지면서 자동으로 재생할 것인지 여부.
    체크 시 자동 실행된다.
    Suffle Playback 음원을 차례 대로 실행할 지, Random으로 섞어 재생할 지 여부.
    체크 시 무작위로 재생된다.
    Default Volumn 기본 볼륨(음악 소리 크기) 설정.
    Repeat Mode 음원을 반복적으로 재생할 지, 각 음원을 1회만 재생할 지 설정.
    Placement of Player Bar 음원 플레이어의 위치를 결정한다.
    페이지 상단과 하단을 선택할 수 있다.
    Show Playlist by Default 음원 목록의 숨김/보임 처리 여부를 설정.
    숨김 상태로 두어도 사용자가 오른쪽 하단 버튼을 클릭하면 나타난다.
  2. 세부 설정을 완료하면 아래의 ‘DONE’ 버튼을 클릭하자.

SCM Music Player

  1. 아래와 같이 HTML 문서 내에 삽입할 수 있는 JavaScript 코드를 준다. 내용은 위에서 설정한 내용 그대로 보여준다. 이 코드를 원하는 위치에 삽입하면 블로그에 SCM Music Player가 나타난다.

SCM Music Player


음원 실행기의 소스코드는 대략 아래처럼 생겼다.

필자가 사용하고 있는 음원 실행기의 설정은 이렇다.

1
2
3
4
5
6
7
8
<!-- SCM Music Player https://www.scmplayer.net -->
<script type="text/javascript" src="https://www.scmplayer.net/script.js"
data-config="{'skin':'skins/scmGreen/skin.css','volume':50,'autoplay':false,'shuffle':true,'repeat':1,'placement':'bottom','showplaylist':false,'playlist':[
{'title':'Imagine - Johnlennon','url':'https://youtu.be/YkgkThdzX-8'},
{'title':'Eric Clapton - Autumn Leaves','url':'https://youtu.be/UQlFOX0YKlQ'},
{'title':'The Beatles - Yesyerday','url':'https://youtu.be/NrgmdOz227I'},
]}" ></script>
<!-- SCM Music Player script end -->

https://www.scmplayer.net/script.js 는 음원 실행기의 API가 들어 있는 실제 js 파일인데 자세한 내용의 설명은 생략하겠다. 일반 사용자가 알아야 할 내용은 없다.

data-config의 설정은 아래와 같다.

구분
설명
skin 맨 처럼 SCM Music Player의 스킨 색상을 표시한다.
volume 기본 볼륨을 표시 0 ~ 99까지 조정하면 된다.
autoplay 자동 실행할 것인지 여부이며 true면 자동 실행, false면 수동 실행이다.
shuffle 실행 중 음원을 무작위로 건너 뛸 것인지 결정한다.
true면 무작위로 건너뛰고, false면 순차적으로 실행한다.
repeat 음원 실행을 전체 몇 번 할 것이냐를 설정한다.
만약 1로 설정했다면 모든 음원을 1번씩 실행 후 종료한다.
placement 음원 실행기를 어디에 위치시킬 것이냐를 결정한다.
top으로 하면 화면 상단, bottom으로 하면 화면 하단에 나타난다.
showplaylist 음원 목록을 기본적으로 표시할 것이냐를 설정한다.
false일 경우 숨긴 상태로 실행하고, true일 경우 보여지는 상태로 실행한다.

필자의 경우는 현재 사용하고 있는 Hexo라는 프레임워크에 위젯(Widget) 형태로 SCM Music Player를 넣어뒀다. 본 블로그 페이지의 소스코드 보기를 하면 소스코드 제일 하단에 전체 음원 목록이 나타난다.

아래와 같은 방식이므로 Youtube 등을 돌아다니다가 좋은 노래가 있다 싶으면 ‘제목’과 ‘주소’를 변경해서 생성된 코드에 추가하면 된다.

1
{'title':'제목','url':'주소'},

필자의 블로그의 하단에는 SCM Music player가 설치되어 있다. 브라우저 하단에 나타나므로 필자 취향의 음원들을 들으실 수 있다. 필자의 경우 Hexo에 Widget으로 넣었는데, Hexo에 Widget으로 설정하여 블로그 전체에 넣는 방법은 향후 본 블로그에서 Hexo를 설명할 때 추가하기로 하겠다.


광고 차단 프로그램은 해제하자

모든 음원은 사실 유투브에서 화면을 제거하고 음원만 가져오는 방식이기 때문에 그냥 유투브를 영상을 보이지 않는 상태에서 음원만 사용한다고 생각하면 된다. 그래서 광고 차단 프로그램을 사용하면 음원이 플레이되지 않는다. SCM Music Player를 본인의 블로그에 설치하려 한다면, 본인 블로그에는 광고차단을 해제해야 음원을 들을 수 있다.


자동 실행은 왠만하면 꺼두자

많은 사용자들이 웹 서핑 시 유투브나 기타 서비스로 음악을 틀어두는 경우가 많으므로, 굳이 SCM Music Player의 자동 실행을 켜두지 않아도 되지 않을까 싶어 필자는 바로는 이를 꺼두기를 제안한다. 본인의 음악적 취향을 알리는 정도로 충분하지 않을까?

필자는 기본 autoplay를 false로 설정해놨다. 필자의 가요/팝 취향이 궁금하신 분들은 아래쪽에서 플레이 리스트를 선택해서 시작하시면 된다. (가요/팝 외 장르들을 넣기는 좀 애매했다. 클래식이나 재즈 같은 것들.)


참고 : 실제 script.js 내용 (2021년 4월 19일 기준)

아래를 클릭하면 필자가 본 글을 쓰는 시점에서의 SCM player의 js script를 볼 수 있다. 그냥 한 번 설정해 두면 알아서 반영되므로, 업데이트 주기 등을 신경 쓸 필요가 없다.

SCM Music Player의 script.js 보기/닫기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
(function() {
var hasFrame = window.parent != window,
scripts = document.getElementsByTagName('script'),
current = scripts[scripts.length - 1],
config = current.getAttribute('data-config'),
head = document.getElementsByTagName("head")[0],
dest = location.href.replace(/scmplayer\=true/g, 'scmplayer=false'),
destHost = dest.substr(0, dest.indexOf('/', 10)),
scm = current.getAttribute('src').replace(/(www.)?(scmplayer.co|scmplayer.net)/, 'scmplayer.net').replace('https:', location.protocol).replace('http:', location.protocol).replace(/script\.js.*/g, 'scm.html') + '#' + dest,
scmHost = scm.substr(0, scm.indexOf('/', 10)),
isOutside = !hasFrame || location.href.indexOf("scmplayer=true") > 0,
postMessage = function(msg) {
return window.top.document.getElementById('scmframe').contentWindow.postMessage(msg, scmHost);
},
postFactory = function(obj, keys) {
var keys = keys.split(','),
post = function(key) {
return function(arg) {
var argStr = '';
if (typeof(arg) != 'undefined')
argStr = (key.match(/(play|queue)/) ? 'new Song(' : '(') +
JSON.stringify(arg) + ')';
postMessage('SCM.' + key + '(' + argStr + ')');
}
};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
obj[key] = post(key);
}
},
postConfig = function(config) {
if (!isOutside)
postMessage('SCM.config(' + config + ')');
},
addEvent = function(elm, evType, fn) {
if (elm.addEventListener)
elm.addEventListener(evType, fn);
else if (elm.attachEvent)
elm.attachEvent('on' + evType, fn);
else
elm['on' + evType] = fn;
},
isIE = (function() {
var undef, v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->', all[0]);
return v > 4 ? v : undef;
})(),
isMobile = navigator.userAgent.match(/iPad|iPhone|Android|Blackberry/i),
isIPad = navigator.userAgent.match(/iPad/i),
init = function() {
if (!document.body) {
setTimeout(init, 10);
return;
}
if (isOutside) outside();
else inside();
},
outside = function() {
var css = 'html,body{overflow:hidden;} body{margin:0;padding:0;border:0;} img,a,embed,object,div,address,table,iframe,p,span,form,header,section,footer{ display:none;border:0;margin:0;padding:0; } #tumblr_controls{display:none;} #scmframe{display:block; background-color:transparent; position:fixed; top:0px; left:0px; width:100%; height:100%; z-index:1667;} ';
var style = document.createElement('style');
style.type = 'text/css';
style.id = 'scmcss';
if (style.styleSheet) style.styleSheet.cssText = css;
else style.appendChild(document.createTextNode(css));
head.appendChild(style);
var scmframe = document.createElement('iframe');
scmframe.frameBorder = 0;
scmframe.id = "scmframe";
scmframe.allowTransparency = true;
scmframe.src = scm;
document.body.insertBefore(scmframe, document.body.firstChild);
var resize = function() {
scmframe.style.height = (function() {
if (typeof(window.innerHeight) == 'number')
return window.innerHeight;
else if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight;
else if (document.body && document.body.clientHeight)
return document.body.clientHeight;
})();
};
addEvent(window, 'load', function() {
setTimeout(function() {
while (document.body.firstChild != scmframe)
document.body.removeChild(document.body.firstChild);
while (document.body.lastChild != scmframe)
document.body.removeChild(document.body.lastChild);
resize();
}, 0);
});
addEvent(window, 'resize', resize);
var getPath = function() {
return location.href.replace(/#.*/, '');
},
path = getPath(),
hash = location.hash;
setInterval(function() {
if (getPath() != path) {
path = getPath();
window.scminside.location.replace(path);
}
if (location.hash != hash) {
hash = location.hash;
window.scminside.location.hash = hash;
}
}, 100);
},
inside = function() {
window.top.document.title = document.title;
var filter = function(host) {
host = host.replace(/blogspot.[a-z.]*/i, 'blogspot.com');
host = host.replace(/^(http(s)?:\/\/)?(www.)?/i, '');
return host;
};
addEvent(document.body, 'click', function(e) {
var tar = e.target;
while (!tar.tagName.match(/^(a|area)$/i) && tar != document.body)
tar = tar.parentNode;
if (tar.tagName.match(/^(a|area)$/i) && !tar.href.match(/.(jpg|png)$/i) && !tar.href.match(/^javascript:/)) {
if (tar.href.indexOf('#') == 0) {
if (tar.href != "#") {
window.top.scminside = window;
window.top.location.hash = location.hash;
e.preventDefault();
}
} else if (tar.title.match(/^(SCM:|\[SCM\])/i)) {
var title = tar.title.replace(/^(SCM:|\[SCM\])( )?/i, '');
var url = tar.href;
SCM.play({
title: title,
url: url
});
e.preventDefault();
} else if (tar.href.match(/\.css$/)) {
window.open('http://scmplayer.net/#skin=' + tar.href, '_blank');
window.focus();
e.preventDefault();
} else if (filter(tar.href).indexOf(filter(location.host)) == -1) {
if (tar.href.match(/^http(s)?/)) {
window.open(tar.href, '_blank');
window.focus();
e.preventDefault();
}
} else if (history.pushState) {
var url = filter(tar.href).replace(filter(destHost), '');
window.top.scminside = window;
window.top.history.pushState(null, null, url);
e.preventDefault();
}
}
});
};
var SCM = {};
postFactory(SCM, 'queue,play,pause,next,previous,volume,skin,placement,' +
'loadPlaylist,repeatMode,isShuffle,showPlaylist,' +
'togglePlaylist,toggleShuffle,changeRepeatMode');
if (window.SCM && window.SCMMusicPlayer) return;
if (!isMobile) {
init();
}
if (config) postConfig(config);
SCM.init = postConfig;
window.SCMMusicPlayer = window.SCMMusicPlayer || SCM;
window.SCM = window.SCM || SCM;
})();