
3歳の子どもが自分で音楽を聞くための、シンプル・低刺激・中毒性の低い音楽プレーヤーアプリを自作しました。
使ったものはWindows PCと「くもんのうた200」のCD、家に転がっていたタブレット、そしてAI。
プログラミングのプの字も分からないわたしでも小一時間で実用的なものが作れたので、作成方法をシェアします。
目的:くもんのうたを健全に聞かせたい
子供に「くもんのうた200」を聴かせたい。「語彙をふやしてくれる」と知育界隈では有名なあのCD、200曲入りの童謡アルバム!
ただし、流し方が問題です。
選択肢1:CDプレーヤーを買う。……場所をとって邪魔だし、そもそも家にはもう「音を出す機器」が十分あるのに、これ以上モノを増やしたくない!
選択肢2:YouTubeで再生する。……こっちも困りもの。おすすめ動画が次々出てくるし、派手なサムネが目に飛び込んできて、気づけば童謡から遠く離れた動画にたどり着いてしまう。音楽を聞かせるつもりが、「画面中毒」になる未来しか見えません。
選択肢3:自分で作る。……よし、やってみよう!
というわけで、家に転がっていたAmazonのFireタブレットに、「くもんのうた200」だけを再生する低刺激なプレーヤーを自作することにしました。

ゴールは曲リストと再生ボタンしかない、究極にシンプルな画面。おすすめなし、広告なし、アニメーションなし、ネット接続もいらない。家の中はもちろん、持ち運んで車の中でも使える仕様が理想です。
用意したもの:5つだけ!
用意したのはこの5つ:
- 「くもんのうた200アルバム」のCD
- タブレット(わたしの場合はFireタブレット。iPadやAndroidタブレットでも応用可)
- Windows PC(MacでもOK)
- CD読み込み用の外付けドライブ(直接CDを読み取れるPCなら不要)
- USBケーブル(データ転送対応のもの)
全体の仕組み
目指す構造はとってもシンプル。
kumon-uta/(フォルダ)
├ index.html ← プレーヤー本体(1ファイル)
└ music/ ← MP3ファイルを入れるフォルダ
├ 001_ぞうさん.mp3
├ 002_チューリップ.mp3
└ ...index.html というファイルをタブレットのブラウザで開くと、同じフォルダ内のMP3を再生するプレーヤーが表示される仕組み。アプリ開発の知識も、サーバーも、月額課金もいりません。
ステップ1:CDからMP3を取り込む
- CDをドライブに入れ、Windows Media Playerアプリを開く
- 左側のメニューに表示されたCD名(「アルバム情報なし」と表示される)をクリック
- 上部の「取り込みの設定」→「形式」→ MP3 を選択(音質は192kbpsで十分)
- 「CDの取り込み」をクリック。これをCD6枚分くり返す
- 取り込まれたファイルは「PC > ミュージック」フォルダに保存されます
つまずきポイント①.cdaファイルの罠
エクスプローラーでCDを開くと「.cda」という拡張子のファイルが見えるけれど、これは音楽データではありません。CDのトラック位置を示す目印みたいなもので、コピーしても再生できないらしい。
無知すぎるわたしはここで10分ほどを無駄にし、AIに指摘されてようやく誤りに気付きました。エクスプローラーではなく、必ず上記のWindows Media Playerで取り込み機能を使うこと。
つまずきポイント②曲名が「トラック1」になる
わたしの環境では、「くもんのうた200アルバム」を読み込んでも曲名データが取得できず、「トラック1.mp3」「トラック2.mp3」……というファイル名になってしまいました。次のステップで一括リネームするので、この時点では気にしなくてOK。
ステップ2:ファイル名を整える
「トラック1.mp3」のままでは流したい曲を探せないので、ここで一気に曲名をつけていきます。
目指すのはこういう形式↓
001_ぞうさん.mp3
002_チューリップ.mp3
...
200_このみち.mp3「通し番号3桁_曲名.mp3」の形式にしておくと、フォルダ内でもプレーヤー内でもちゃんと曲順どおりに並びます。
一曲ずつ手作業で曲名を直すのは面倒くさすぎるので、PowerShellというWindows標準のツールを使って、テキストファイル1つで一括修正していきます。ちょっと専門的に見えるけれど、コピペするだけなので実際は超簡単!
①MP3の入っている music フォルダ(この段階では「アルバム情報なし」のフォルダが6つ入ってるはず)を開いて、「曲名リスト.txt」という空のテキストファイルを新規作成する(右クリック → 新規作成 → テキストドキュメント)
②メモ帳でそのファイルを開いて、曲名を1行に1曲ずつ入力する(下の開閉ボックスから曲名をコピペすると楽!)
「くもんのうた200アルバム」全200曲リスト(クリックで展開)
- ぞうさん
- チューリップ
- ぶんぶんぶん
- はと
- おうま
- どんぐりころころ
- とんぼのめがね
- おつかいありさん
- だるまさん
- げんこつやまのたぬきさん
- おおきなたいこ
- みずあそび
- サッちゃん
- ちょうちょ
- おはながわらった
- あひるのぎょうれつ
- かえるのうた
- かたつむり
- シャボンだま
- おおきなくりのきのしたで
- メリーさんのひつじ
- こいのぼり
- ゆうやけこやけ
- つき
- うさぎ
- かわいいかくれんぼ
- めだかのがっこう
- こぶたぬきつねこ
- いぬのおまわりさん
- むすんでひらいて
- とけいのうた
- すうじのうた
- おすもうくまちゃん
- おもちゃのマーチ
- ことりのうた
- きらきらぼし
- ゆき
- おしょうがつ
- かたたたき
- てをたたきましょう
- おはなしゆびさん
- おかあさん
- ないしょばなし
- くつがなる
- ななつのこ
- ゆうひ
- たなばたさま
- やまのおんがくか
- うさぎのダンス
- いとまきのうた
- うみ
- ゆりかごのうた
- しょうじょうじのたぬきばやし
- こぎつね
- あかとんぼ
- たきび
- とおりゃんせ
- かごめかごめ
- アイアイ
- おべんとうばこのうた
- うさぎとかめ
- ももたろう
- うらしまたろう
- わらいかわせみにはなすなよ
- やぎさんゆうびん
- もりのくまさん
- あめふりくまのこ
- とんでったバナナ
- そうだったらいいのにな
- おおきなふるどけい
- おもちゃのチャチャチャ
- きしゃポッポ
- うたのまち
- かもめのすいへいさん
- ドレミのうた
- じゅうにんのインディアン
- しあわせならてをたたこう
- ふしぎなポケット
- おなかのへるうた
- バナナのおやこ
- おんまはみんな
- もりのこびと
- うれしいひなまつり
- ぼうがいっぽん
- いっぽんでもにんじん
- ロンドンばし
- まっかなあき
- ピクニック
- クラリネットをこわしちゃった
- ジングルベル
アルバム② disc 1(91〜129曲)
- あがりめさがりめ
- あたまかたひざポン
- いっぽんばしこちょこちょ
- おてらのおしょうさん
- パンダうさぎコアラ
- やきいもグーチーパー
- グーチョキパーでなにつくろう
- とんとんとんとんひげじいさん
- あくしゅでこんにちは
- ちいさなはたけ
- てをつなごう
- おちゃらかほい
- ずいずいずっころばし
- あんたがたどこさ
- アルプスいちまんじゃく
- ひらいたひらいた
- あかいとりことり
- かくれんぼ
- はしるのだいすき
- おにのパンツ
- ぶらんこ
- どんないろがすき
- アビニヨンのはしのうえで
- おたんじょうびのうた
- あかいぼうししろいぼうし
- おばけなんてないさ
- とんとんともだち
- みなみのしまのハメハメハだいおう
- さんぽ
- わらいごえっていいな
- ピクニック・マーチ
- たのしいね
- マーチング・マーチ
- ぼくのミックスジュース
- せかいじゅうのこどもたちが
- にじ
- てのひらをたいように
- およげ!たいやきくん
- ABCのうた
アルバム② disc 2(130〜168曲)
- どこでねるの
- あらどこだ
- いけのこい
- かっこう
- しずかなこはん
- やまのワルツ
- こんこんくしゃんのうた
- おさるのかごや
- ジャングルポケット
- ねこふんじゃった
- くじらのとけい
- バスにのって
- バスごっこ
- はたらくくるま
- でんしゃごっこ
- きしゃ
- ちかてつ
- せんろはつづくよどこまでも
- うちゅうせんのうた
- トマト
- カレーライスのうた
- きのこ
- くいしんぼおばけ
- ドロップスのうた
- アイスクリームのうた
- あさいちばんはやいのは
- はやおきどけい
- ゆうがたのおかあさん
- おふろうた
- おふろジャブジャブ
- たろうさんのあかちゃん
- にんげんっていいな
- はるよこい
- どこかではるが
- うぐいす
- さくらさくら
- はるがきた
- はるのおがわ
- おもいでのアルバム
アルバム② disc 3(169〜200曲)
- いちねんせいになったら
- ちゃつみ
- せいくらべ
- あめふり
- ほたるこい
- キャンプだほい
- はなび
- むしのこえ
- もみじ
- まつぼっくり
- ちいさいあきみつけた
- あわてんぼうのサンタクロース
- あかはなのトナカイ
- きよしこのよる
- たこのうた
- きたかぜこぞうのかんたろう
- スキー
- まめまき
- こもりうた
- いちばんぼしみつけた
- まちぼうけ
- あかいくつ
- ふじのやま
- つきのさばく
- おぼろづきよ
- ふるさと
- みかんのはなさくおか
- あのまちこのまち
- きんたろう
- いっすんぼうし
- むらまつり
- このみち
※上記は「くもんのうた200アルバム①②」の収録曲リストです。詳細やCD購入はくもん出版公式サイトをご確認ください。曲順は「くもんのうた200えほん」の掲載順に対応しています。
③保存するとき、「文字コード」をUTF-8にする(メモ帳の下の方に選択欄あり)
④同じmusic フォルダ内に「rename.ps1」という名前で、下のスクリプトをコピペしたテキストファイルを作る
$songs = Get-Content -Path ".\曲名リスト.txt" -Encoding UTF8
$i = 1
foreach ($song in $songs) {
$oldName = "トラック$i.mp3"
$newName = "{0:D3}_{1}.mp3" -f $i, $song
if (Test-Path $oldName) {
Rename-Item -Path $oldName -NewName $newName
Write-Host "$oldName → $newName"
}
$i++
}
Write-Host "完了!"
Read-Host "Enterキーで閉じます"⑤フォルダのアドレスバーに powershell と入力してEnter → 開いた画面で .\rename.ps1 と入力してEnter。
ずらーっとファイル名が書き換わって「完了!」と表示されたら成功です。200曲のリネームでも10秒で終わるはず!
リネームが終わったら、デスクトップに kumon-uta フォルダを作って、さらにその中に music フォルダを作り、リネームした200曲分のMP3を全部入れます。
ステップ3:プレーヤー本体(index.html)を作る
ここが心臓部。AIにこれらの要望を伝えてコードを書いてもらいました。
- 大きな再生ボタンと曲リストだけの低刺激でシンプルな画面
- 曲が終わると自動で次へ。最後まで行くと1曲目に戻る
- 前回聴いていた曲を記憶する
- 曲リストはHTML内に直接書いてあるので、テキスト編集だけで曲の追加・変更が可能
下記のコードをメモ帳などに貼り付けて index.html という名前で保存し、kumon-uta フォルダに入れます。保存時に文字コードを「UTF-8」にするのを忘れずに!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>どうよう プレーヤー</title>
<style>
:root {
--cream: #FBF6E4; --card: #FFFFFF; --ink: #4A4238;
--ink-soft: #8A8071; --red: #D94F45;
--highlight: #F9EBBD; --line: #EFE7D2;
}
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
font-family: sans-serif; background: var(--cream); color: var(--ink);
display: flex; flex-direction: column; overflow: hidden;
}
.now {
background: var(--card); border-bottom: 2px solid var(--line);
padding: 20px 20px 14px; text-align: center; flex-shrink: 0;
}
.now .disc-label { font-size: 14px; color: var(--ink-soft); letter-spacing: 2px; margin-bottom: 6px; }
.now .title-row { display: flex; align-items: center; justify-content: center; gap: 12px; min-height: 44px; }
.num-badge {
background: var(--red); color: #fff; font-size: 16px; font-weight: bold;
min-width: 34px; height: 34px; border-radius: 8px;
display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.now .song-title { font-size: 26px; font-weight: bold; line-height: 1.3; }
.progress-wrap { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.time { font-size: 13px; color: var(--ink-soft); min-width: 42px; }
input[type="range"] { flex: 1; -webkit-appearance: none; appearance: none; height: 26px; background: transparent; }
input[type="range"]::-webkit-slider-runnable-track { height: 8px; background: var(--line); border-radius: 4px; }
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none; width: 26px; height: 26px; border-radius: 50%;
background: var(--red); margin-top: -9px; border: 3px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.controls {
display: flex; align-items: center; justify-content: center; gap: 28px;
padding: 14px 0 18px; background: var(--card); border-bottom: 2px solid var(--line); flex-shrink: 0;
}
button {
border: none; background: var(--cream); color: var(--ink); border-radius: 50%;
cursor: pointer; display: flex; align-items: center; justify-content: center;
}
button:active { background: var(--highlight); }
.btn-skip { width: 64px; height: 64px; }
.btn-skip svg { width: 30px; height: 30px; fill: var(--ink); }
.btn-play { width: 92px; height: 92px; background: var(--red); }
.btn-play:active { background: #C24239; }
.btn-play svg { width: 42px; height: 42px; fill: #fff; }
.list { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: 30px; }
.disc-header { padding: 18px 20px 8px; font-size: 15px; font-weight: bold; color: var(--ink-soft); letter-spacing: 2px; }
.song {
display: flex; align-items: center; gap: 14px; padding: 15px 20px;
font-size: 19px; border-bottom: 1px solid var(--line); cursor: pointer;
}
.song:active { background: var(--highlight); }
.song.playing { background: var(--highlight); font-weight: bold; }
.song .n { color: var(--red); font-weight: bold; font-size: 15px; min-width: 36px; text-align: right; flex-shrink: 0; }
.song.playing .note { margin-left: auto; color: var(--red); font-size: 18px; }
</style>
</head>
<body>
<div class="now">
<div class="disc-label" id="discLabel"></div>
<div class="title-row">
<span class="num-badge" id="numBadge"></span>
<span class="song-title" id="songTitle"></span>
</div>
<div class="progress-wrap">
<span class="time" id="curTime">0:00</span>
<input type="range" id="seek" min="0" max="100" value="0" step="0.1">
<span class="time" id="durTime">0:00</span>
</div>
</div>
<div class="controls">
<button class="btn-skip" id="btnPrev" aria-label="まえの曲">
<svg viewBox="0 0 24 24"><path d="M6 6h2v12H6zm3.5 6 8.5 6V6z"/></svg>
</button>
<button class="btn-play" id="btnPlay" aria-label="再生 / いちじていし">
<svg id="iconPlay" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
<svg id="iconPause" viewBox="0 0 24 24" style="display:none"><path d="M6 5h4v14H6zm8 0h4v14h-4z"/></svg>
</button>
<button class="btn-skip" id="btnNext" aria-label="つぎの曲">
<svg viewBox="0 0 24 24"><path d="M16 6h2v12h-2zM6 18l8.5-6L6 6z"/></svg>
</button>
</div>
<div class="list" id="list"></div>
<audio id="audio" preload="auto"></audio>
<script>
// ==================================================
// 曲リスト:ここを自分の曲に書き換えてください。
// ファイル名は「通し番号3桁_曲名.mp3」で music フォルダへ。
// グループ(ディスク)はいくつ増やしてもOK。
// ==================================================
const DISCS = [
{ label: "ディスク 1", songs: [
"ぞうさん","チューリップ","ぶんぶんぶん" // ...お手持ちの曲名を並べる
]},
{ label: "ディスク 2", songs: [
"とけいのうた","すうじのうた" // ...
]}
];
const TRACKS = [];
DISCS.forEach(disc => {
disc.songs.forEach(title => {
const num = TRACKS.length + 1;
TRACKS.push({
num, title, disc: disc.label,
file: "music/" + String(num).padStart(3, "0") + "_" + title + ".mp3"
});
});
});
const audio = document.getElementById("audio");
const list = document.getElementById("list");
let current = 0;
try {
const saved = parseInt(localStorage.getItem("lastTrack"), 10);
if (!isNaN(saved) && saved >= 0 && saved < TRACKS.length) current = saved;
} catch (e) {}
let lastDisc = "";
TRACKS.forEach((t, i) => {
if (t.disc !== lastDisc) {
const h = document.createElement("div");
h.className = "disc-header";
h.textContent = t.disc;
list.appendChild(h);
lastDisc = t.disc;
}
const row = document.createElement("div");
row.className = "song";
row.id = "song-" + i;
row.innerHTML = '<span class="n">' + t.num + '</span><span>' + t.title + '</span><span class="note"></span>';
row.addEventListener("click", () => { load(i); play(); });
list.appendChild(row);
});
function load(i) {
current = (i + TRACKS.length) % TRACKS.length;
const t = TRACKS[current];
audio.src = encodeURI(t.file);
document.getElementById("songTitle").textContent = t.title;
document.getElementById("numBadge").textContent = t.num;
document.getElementById("discLabel").textContent = t.disc;
document.querySelectorAll(".song").forEach(el => el.classList.remove("playing"));
const row = document.getElementById("song-" + current);
row.classList.add("playing");
row.querySelector(".note").textContent = "♪";
row.scrollIntoView({ block: "nearest" });
try { localStorage.setItem("lastTrack", current); } catch (e) {}
}
function play() { audio.play(); }
function pause() { audio.pause(); }
document.getElementById("btnPlay").addEventListener("click", () => {
if (audio.paused) play(); else pause();
});
document.getElementById("btnPrev").addEventListener("click", () => { load(current - 1); play(); });
document.getElementById("btnNext").addEventListener("click", () => { load(current + 1); play(); });
audio.addEventListener("ended", () => { load(current + 1); play(); });
audio.addEventListener("play", () => {
document.getElementById("iconPlay").style.display = "none";
document.getElementById("iconPause").style.display = "block";
});
audio.addEventListener("pause", () => {
document.getElementById("iconPlay").style.display = "block";
document.getElementById("iconPause").style.display = "none";
});
const seek = document.getElementById("seek");
let seeking = false;
function fmt(s) {
if (!isFinite(s)) return "0:00";
const m = Math.floor(s / 60), sec = Math.floor(s % 60);
return m + ":" + String(sec).padStart(2, "0");
}
audio.addEventListener("timeupdate", () => {
if (!seeking && audio.duration) seek.value = (audio.currentTime / audio.duration) * 100;
document.getElementById("curTime").textContent = fmt(audio.currentTime);
});
audio.addEventListener("loadedmetadata", () => {
document.getElementById("durTime").textContent = fmt(audio.duration);
});
seek.addEventListener("input", () => { seeking = true; });
seek.addEventListener("change", () => {
if (audio.duration) audio.currentTime = (seek.value / 100) * audio.duration;
seeking = false;
});
audio.addEventListener("error", () => {
if (audio.src) document.getElementById("songTitle").textContent = "ファイルが見つかりません";
});
load(current);
</script>
</body>
</html>保存したら、まずPC上で index.html をダブルクリックして動作確認しましょう。ブラウザでプレーヤーが開いて、曲が再生できたら成功!
ステップ4:タブレットに転送する
- タブレットとPCをUSBケーブルでつなぐ
- タブレット側で「ファイル転送」モードを選ぶ
- PCのエクスプローラーにタブレットが表示されたら、「内部ストレージ」直下に
kumon-utaフォルダごとコピー
つまずきポイント③PCからタブレットの中身が空に見える
これは接続直後のタブレットが「充電のみ」モードになっているのが原因です。タブレットの画面ロックを解除して、通知パネルからUSB接続の通知をタップ→「ファイル転送」を選ぶと「内部ストレージ」が表示されるはず!
ステップ5:タブレットで開く(機種別)
ここが機種によって一番違うところ。
Fireタブレットの場合(わたしのケース)
標準のSilkブラウザは、バージョンによって file:// でのローカルファイル閲覧をブロックしています(わたしの環境ではダメでした)。なので「Fully Kiosk Browser」という無料アプリを使いました。
このアプリはAmazonアプリストアにはなくて、公式サイト(fully-kiosk.com)からAPKファイルを入手してダウンロードする方式。
- 設定 → セキュリティとプライバシー → 「不明ソースからのアプリ」でSilkを許可
- Silkで fully-kiosk.com を開いて、Helpページ内の「Download APK Files」ボックスから「Fully Kiosk Browser APK for Fire OS」をダウンロード(見つからなければ通常のAndroid用APKでも動く)
- ダウンロード通知からタップしてインストール
- 起動して、Start URLに
file:///sdcard/kumon-uta/index.htmlを設定すれば曲が再生可能に!
Androidタブレットの場合
Chromeのアドレスバーに以下を入力すれば、すぐに開けるはず。
file:///sdcard/kumon-uta/index.html開けたらブックマークやホーム画面追加をしておきましょう。
iPadの場合
iPadのSafariはローカルHTMLの直接オープンが苦手なので、少し工夫が必要な模様。「Documents by Readdle」などのファイル管理アプリにフォルダごと入れて、アプリ内でHTMLを開く方法が比較的手軽なようです。
運用してみてわかったこと
- アプリを開いたまま画面ロックすると、次のタブレット立ち上げ時にいきなり曲が流れだすことがあります。音量注意!
- 曲を足したいときは、MP3を
musicフォルダに追加して、index.htmlの曲リストに曲名を追記するだけ。アプリの再インストール等は不要です - 元のCDと取り込んだファイルはPC側にバックアップを残しておくと安心
画面中毒を無事回避

完成した音楽プレーヤーを渡したときの子どもの反応といったら!「この曲知ってる!」「本のこのページの曲だよね」と目をキラキラさせながら楽しんでくれて、見ている親までほっこり。
それでいて、お風呂やご飯の時間になったらサクッとタブレットを置いて行動できていて、画面中毒になっていない様子に一安心しました。
かかったコストは「くもんのうた200アルバム」の約6,000円弱と小一時間だけ。あとは家にあったタブレットだけで、月額課金なし、広告なし、ネット接続もいらない音楽プレーヤーが手に入ってしまった……!
「CDプレーヤーは邪魔、でもYouTubeは刺激強すぎ」への解決策が、AIの力を借りれば短時間で形にできてしまうだなんて、いい時代に生まれたものです。