audioタグの操作(ダウンロードされないようにする)

  • このエントリーをはてなブックマークに追加

音楽プレーヤー
先日、音声ファイル再生ページの叩き台を作れと言われたので、
とりあえず、やってみてました。
(あんまりそういうの得意じゃないんだけどなー)

せっかくなので、それをブログネタにしたいと思います。
 
 
要件は以下のとおり。
・音声は、ユーザーによる操作によって再生する。
・ストリーミングサーバーを立てず、かつ、音声ファイルのURLを隠したい。(Downloadさせない)

ふむ。

なんだかんだ割り切って、まずはどこまで”素人”ではわからないようにできるか。
そのレベルでいろいろと手法を探していると、

・音声再生が始まったらsourceタグを消す

というのが結構有効なのかな?と思い、その方向性でせっせとコーディングしてみました。
せっかくなのでどなたかの参考になればと思って、自身がやってみた最終形を残します。
(ブログ記事を書いたという実績稼ぎの側面が無くはないです)

<各種ファイルの配置構成>
main.html
sample_js.php
  │
  └─voice
    │
    ├─audio1.mp3
    ├─audio2.mp3
    └─audio3.mp3

まずはjsファイル(を今回はphpファイルとして作ったもの)。

一応、このファイルにGETパラメータをIDとして渡すことで、
直接的に音声ファイル名はわからないようにしました。
また、ソースファイルも直接見れないようにリファラをチェックしてます。
※その辺りのことがしたかったのでphpとしました


<?php
    $ref = getenv("HTTP_REFERER"); 
    if (0 !== strpos($ref, 'https://www.genio.co.jp/')) {
        echo $errmsg = '不正なアクセスです。';
        exit();
    }

    // キャッシュさせない
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    header( 'Cache-Control: post-check=0, pre-check=0', FALSE );

    // JS外部ファイルであるのを知らせる
    // ※メディアタイプと文字コードをセット
    header('Content-Type: application/x-javascript; charset=utf-8');

    // 各音声ファイルリスト
    $voice_list = array('sample1.mp3', 'sample2.mp3', 'sample3.mp3', );

    // getパラメータの「id」により音声ファイルを特定
    $voice_id = $_GET["id"];

    // audio の source要素をDOMに追加する
?>
    var source_element = document.createElement("source");
    source_element.setAttribute("id"  , "voice_file");
    source_element.setAttribute("src" , "voice/<?= $voice_list[$voice_id]; ?>");
    source_element.setAttribute("type", "audio/mp3");

    var parent_object = document.getElementById("answer_voice");
    parent_object.appendChild(source_element);

そしてページ本体のhtmlファイル。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>音声ファイルダウンロード禁止検証</title>
    <style type="text/css">
    <!--
        割愛します
    //-->
    </style>
    <script type="text/javascript">
        //--------------------------------------------------
        // 音声関連のインクルードscriptタグを削除
        //--------------------------------------------------
        function decide_script()
        {
            // インクルードしたscriptファイルタグを削除
            // ※[0]は当scriptタグ、[1]がbody下部にインクルードする外部ファイルを指す
            var script_element = document.getElementsByTagName('script')[1];
            script_element.parentNode.removeChild( script_element );
        }
        function decide_source()
        {
            // audioのsourceタグを削除
            var voice_element = document.getElementById('voice_file');
            if (voice_element)
            {
                voice_element.removeAttribute('src');
            }
        }
        //--------------------------------------------------
        // 音声再生
        //--------------------------------------------------
        function listen()
        {
            // 音声ソース出力
            var script_elemet = document.createElement("script");
            script_elemet.setAttribute('id'  , 'voice_js');
            script_elemet.setAttribute('src' , 'sample_js.php?id=0');
            script_elemet.setAttribute('type', 'text/javascript');
            var parent_elemet = document.getElementById('audio_designate');
            parent_elemet.appendChild(script_elemet);

            // 音声再生
            document.getElementById('answer_voice').play();

            // 音声ソース削除
            decide_script();

            // 音声ソースのsourceタグ削除
            var file_element = document.getElementById('voice_file');
            if (file_element)  file_element.parentNode.removeChild( file_element );
        }
        //--------------------------------------------------
        // 音声停止
        //--------------------------------------------------
        function stop()
        {
            document.getElementById('answer_voice').pause();
            document.getElementById('answer_voice').currentTime = 0;
        }
        //--------------------------------------------------
        // 音声一時停止
        //--------------------------------------------------
        function pause()
        {
           document.getElementById('answer_voice').pause();
        }
    </script>
</head>
<body oncontextmenu="return false" onload="">
    <table class="main">
        <tr><td>

        <!-- 音声ファイル操作ボタン -->
        <input type="button" onclick="listen();" value="再生">
        <input type="button" onclick="stop();" value="止める">
        <input type="button" onclick="pause();" value="一時停止">

        <audio id="answer_voice" preload="auto" onplay="decide_source();">
            <p>※ご利用のブラウザでは音声再生することができません。</p>
            <!-- sourceタグ動的出力箇所 -->
        </audio>

        </td></tr>
    </table>

    <!-- 音声ファイル指定 -->
    <div id="audio_designate">
        <!-- scriptタグ動的出力箇所 -->
    </div>
</body>
</html>

再生ボタンを押下すると、以下のような動きになります。

①下から5行目の<!– scriptタグ動的出力箇所 –>に、jsのインクルードタグが挿入される。
②下から13行目の<!– sourceタグ動的出力箇所 –>に、jsによって audio の source タグが挿入される。
③mp3を再生して、すぐに①で挿入したscriptタグを削除する。
④audioタグでonplayイベントが発生したら、②で挿入した source タグを削除する。

これで少なくとも、コンテキストメニューのソース表示では、
音声ファイルの在処はわからなくできたんじゃないでしょうか。
DOMについても、チラッとは出ると思いますけど、基本的にはすぐ消えるし。

あとをどうするかは現役のプログラマーにお任せすることにして、
老兵はただ(無責任に)去りゆくのみ、です。

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*