Post

자바스크립트: 인터넷에서 미디(MIDI) 파일을 바로 재생하는 라이브러리(http://www.midijs.net/) + 예제: 미디 플레이어

자바스크립트: 인터넷에서 미디(MIDI) 파일을 바로 재생하는 라이브러리(http://www.midijs.net/) + 예제: 미디 플레이어

혹시 자바스크립트 라이브러리를 사용하지 않고 스프링 부트를 이용해 직접 미디를 mp3로 변환하는 방법을 찾고있다면 이 페이지를 방문해보세요.

gist에서 예제 코드 보기

미디 플레이어 실행하기

PHP 기반으로 만든 미디 플레이어입니다. MIDI란 컴퓨터 음악을 위한 규격화된 포맷으로 미디 표준을 지켜 만든 음악 파일들은 미디 플레이어 등에서 실행할 수 있으며 오늘날 음악 제작에서 필수적으로 사용되고 있습니다. 자세한 내용

예제로 만든 미디 플레이어에는 다음 기능이 구현되어 있습니다.

  • MIDI.js 라이브러리를 이용한 미디파일 재생, 일시정지 및 정지
  • 파일 정보, 재생 시간, 현재 재생 시간을 실시간으로 표시
  • 현재 곡 재생이 완료되면 자동으로 다음 곡을 재생하는 기능
  • 다음곡 재생 기능은 일시정지시  일시정지된 시간도 고려
  • 정지 버튼 클릭시에는 다음 곡을 재생하지 않음

라이브러리는 http://www.midijs.net/ 에서 자세한 사용법을 볼 수 있습니다.

 

1. CDN

1
<script type='text/javascript' src='//www.midijs.net/lib/midi.js'></script>

반드시 위의 주소만 이용 가능하며, 자바스크립트 파일만 따로 가져오거나 본인의 서버에 저장해서 사용하는 것은 불가능합니다. 지금은 안정적으로 서비스중입니다만, 만약 제작자가 서비스를 종료한다면 이 라이브러리는 더 이상 사용할 수 없습니다.

 

2. 주요 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 재생 시작
 MIDIjs.play(url)

// 재생 멈춤
 MIDIjs.stop()

// 일시정지 (인터넷 익스플로러 사용 불가)
 MIDIjs.pause()

// 일시정지 해제 (인터넷 익스플로러 사용 불가)
 MIDIjs.resume()

// 미디 파일 총 길이(시간) 얻어오기 (인터넷 익스플로러 9 버전 이하 사용 불가) - 초(s) 단위
 MIDIjs.get_duration(url, callback)

// 미디 파일 시간을 콘솔 로그에 기록하는 예제
 MIDIjs.get_duration("http://www.midijs.net/hinematov.mid", function(seconds) { console.log("Duration: " + seconds);} )

1
2
3
4
5
6
7
8
9
10
11
// 현재 오디오 상태 정보 얻어오기
 MIDIjs.get_audio_status()

// 현재 상태 및 에러 메시지 얻어오기 (실시간)
// 메시지 갱신때마다 호출할 콜백 함수 작성
function display_message(mes) {
     [HTML요소].innerHTML = mes;
};

// 콜백 함수를 이벤트에 지정
MIDIjs.message_callback = display_message;
1
2
3
4
5
6
7
8
9
// 플레이어 이벤트 가져오기 (실시간)

// 콜백 함수 작성
function display_time(ev) {
     [HTML요소].innerHTML = ev.time; // 재생 시작 후 초당 시간 정보를 가져옴 (현재 재생 위치)
};

// 이벤트 지정
MIDIjs.player_callback = display_mesage;

 

3. 예제 코드 작성 (일부분)

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
 // 밀리초 또는 초를 분:초 포맷으로 변환  
 Number.prototype.toMS = function(isMillisecond) {
    if (isMillisecond) {
        var num = parseInt(this) / 1000
    } else {
        var num = parseInt(this)
    }

    // console.log(num)
    var min = Math.floor(num / 60)
    var sec = Math.floor(num - (min * 60))
    if (min < 10) {
        min = "0" + min;
    }
    if (sec < 10) {
        sec = "0" + sec;
    }
    return min + ":" + sec
}

// 다음 재생 기능 구현에 필요한 변수들을 모은 객체
const global_toNext = {
    timeout: null,
    totalDuration: 0,
    currentTime: 0,
    targetEl: null
}

window.onload = function() {

    var global_isPlaying = false;
    const regex1 = /^Playing: .*$/g

    console.log(MIDIjs.get_audio_status());

    // setTimeout 기능을 이용해 다음 곡 기능 구현
    function nextCaller(time, targetEl){
        if(global_toNext.timeout){
            clearTimeout(global_toNext.timeout)
        } 
        global_toNext.targetEl = targetEl
        global_toNext.timeout = setTimeout(()=>{
            targetEl.trigger("click")
        }, time + 5000)
        
    }

    $(".pseudoLink").click(e => { // 곡 목록을 클릭하면 미디 파일을 재생

        MIDIjs.play(e.target.dataset.url)
        MIDIjs.get_duration(e.target.dataset.url, function(seconds) {
            $("#title").text(e.target.innerText)
            $("#btnPause").data("playing", "true")
            $("#total_time").text(seconds.toMS())
            global_toNext.totalDuration = parseInt(seconds) * 1000
            global_isPlaying = true;
            
            $(".pseudoLink.text-info").removeClass("text-info")
            $(".pseudoLink.text-warning").removeClass("text-warning")
            $(e.target).addClass("text-info")
            // alert(seconds)
            // setInterval을 이용하여 곡이 로딩중인 경우에는 액션을 취하지 않고, 곡이 로딩 완료된 경우에는
            // 재생 시간과 다음에 재생할 곡을 다음 곡 기능 함수에 넘김
            const sw1 = setInterval(() => {
                const msg = $("#playInfo").text().trim()
                if(regex1.test(msg)){
                    const time = parseInt(seconds) * 1000
                    const targetEl = $(e.target).next()
                    console.log(msg, targetEl)
                    nextCaller(time, targetEl)
                    
                    clearInterval(sw1)
                }
            }, 100)
        })

        $("#btnPause .material-icons").html("pause")

        return false;
    })

    $("#btnPause").on("click", e => { // 일시정지 기능

        console.log(global_isPlaying)

        if (global_isPlaying == true) {
            MIDIjs.pause()
            global_isPlaying = false
            $("#btnPause .material-icons").html("play_arrow")
            clearTimeout(global_toNext.timeout)
            $(".pseudoLink.text-info").removeClass("text-info").addClass("text-warning")
        } else {
            MIDIjs.resume()
            global_isPlaying = true
            $("#btnPause .material-icons").html("pause")
            nextCaller(global_toNext.totalDuration - global_toNext.currentTime, global_toNext.targetEl)
            $(".pseudoLink.text-warning").addClass("text-info").removeClass("text-warning")
        }

    })

    $("#btnStop").click(e => { // 정지 기능
        MIDIjs.stop()
        clearTimeout(global_toNext.timeout)
        $(".pseudoLink.text-info").removeClass("text-info")
        $(".pseudoLink.text-warning").removeClass("text-warning")
    })

    // MIDI.js 관련 부분
    var message_span = document.getElementById('MIDIjs.message');
    message_span.innerHTML = MIDIjs.get_audio_status();

    MIDIjs.message_callback = display_status;

    function display_status(message) {
        message_span.innerHTML = message;
    };

    var time_span = document.getElementById('MIDIjs.audio_time');
    MIDIjs.player_callback = display_time;

    function display_time(player_event) {
        time_span.innerHTML = player_event.time.toMS();
        global_toNext.currentTime = player_event.time * 1000
    };

}

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
    <?php
         function iterateDirectory($i)
        {
            foreach ($i as $path) {
                if ($path->isDir())
                {
                    iterateDirectory($path);
                }
                else
                {
                  $r_path = str_replace("\\", "/", $path);
                  $v_path = str_replace("./files/", "", $r_path);

                    echo ''
                      .'<a href="#" class="pseudoLink list-group-item list-group-item-action" data-url="'.$r_path.'">'
                      .$v_path
                      .'</a>';
                }
            }

        }

        $dir = './files';
        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));

        iterateDirectory($iterator);
?>

 

class="img-link shimmer" >

class="img-link shimmer" >

This post is licensed under CC BY 4.0 by the author.