This is a simple example of how to play audio.
tr.phpsearches (tr.php?word1/word2words are separated by slashes, by default matches any words, unless.ais one of the path components, then it matches all)playmusic.phppresents an HTML page with an embedded audio playerplayaudio.phpstreams the audio file
playaudio.php
<?php
$qs = $_SERVER['QUERY_STRING'];
$fn = urldecode($qs);
$path = "/music/$fn";
if( file_exists($path) ) {
$mime = mime_content_type($path);
header('Content-Type: audio/mpeg');
header('Content-length: ' . filesize($path));
$fh = fopen($path, 'rb');
fpassthru($fh);
fclose($fh);
} else {
http_response_code(404);
echo "does not exist: $path";
exit();
}
playmusic.php
<?php
function show_player($path,$rpath,$mime) {
$xs = explode("/",$path);
$fn = array_pop($xs);
$enc = urlencode($rpath);
?><!DOCTYPE html>
<html>
<head>
<title>Audio: <?php echo $fn; ?></title>
</head>
<body>
<h1><?php echo $fn; ?></h1>
<p class='path'><?php echo $rpath; ?></p>
<div class='player'>
<audio controls src="/playaudio.php?<?php echo $enc; ?>"></audio>
</div>
</body>
</html><?php
}
$qs = $_SERVER['QUERY_STRING'];
$fn = urldecode($qs);
$path = "/music/$fn";
if( file_exists($path) ) {
$mime = mime_content_type($path);
show_player($path,$fn,$mime);
} else {
echo "does not exist: $path";
}
tr.php
The sqlite3 database /music/music.byword.db contains a single table with two columns: word and paths.
The paths column contains JSON-encoded lists of paths. These indices are made by a python script and
the find command.
<?php
$dbfn = "/music/music.byword.db";
if( ! file_exists($dbfn) ) {
echo "no db";
exit();
}
$db = new SQLite3($dbfn, SQLITE3_OPEN_READWRITE);
function get1($word) {
global $db;
$stmt = $db->prepare("SELECT paths FROM tracks_by_word WHERE word = :word");
$stmt->bindValue(":word",$word);
$result = $stmt->execute();
$got = $result->fetchArray(SQLITE3_NUM);
if( $got === false ) {
echo "got false";
return [];
}
$got = $got[0];
$paths = json_decode($got);
return $paths;
}
$qs = $_SERVER['QUERY_STRING'];
$qs = strtolower($qs);
$ws = explode("/",$qs);
$all = false;
$words = [];
foreach($ws as $word) {
if( $word == ".a" ) {
$all = true;
} else if( $word !== "" ) {
array_push($words,$word);
}
}
if( count($words) == 0 ) {
echo "no words";
exit();
}
if( $all ) {
$found = [];
echo "all words: ".implode(", ",$words);
$word1 = array_shift($words);
$f = get1($word1);
foreach($f as $p) {
$found[$p] = true;
}
foreach($words as $word) {
$f = get1($word);
$g = [];
foreach($f as $x) {
$g[$x] = true;
}
foreach($found as $k => $v) {
if( !array_key_exists($k,$g) ) {
unset($found[$k]);
}
}
}
} else {
echo "any words: ".implode(", ",$words);
$found = [];
foreach($words as $word) {
$f = get1($word);
foreach($f as $p) {
$found[$p] = true;
}
}
}
// print results
{
$found = array_keys($found);
if( count($found) == 0 ) {
echo "found nothing";
exit();
}
sort($found);
echo "<ol>\n";
foreach($found as $path) {
if( preg_match('@\.\./@',$path) ) {
echo ".. in path";
exit();
}
$p = urlencode($path);
$url = "/playmusic.php?$p";
echo "<li><a target='_blank' href='$url'>$path</a></li>\n";
}
echo "</ol>\n";
}
mkwordidx
Takes file index (produced using find), splits at non-alphanumeric into words,
converts to lowercase, and makes a dict mapping word to path.
import json, re
from collections import defaultdict
d = defaultdict(list)
a = open("music.index.txt").read().rstrip().splitlines()
for x in a:
if x.startswith("./"):
x = x[2:]
y = x.lower()
y = re.sub(r"[^a-zA-A0-9]+","_",y)
y = re.sub(r"__+","_",y)
xs = y.split("_")
for word in xs:
if word != "":
d[word].append(x)
with open("music.byword.json","wt") as f:
json.dump(d,f)
mkwordsql
Reads the JSON from above and inserts it into an sqlite3 database.
import json, sqlite3, os
with open("music.byword.json") as f:
d = json.load(f)
dbfn = "music.byword.db"
if os.path.exists(dbfn):
os.unlink(dbfn)
con = sqlite3.connect(dbfn)
cur = con.cursor()
cur.execute("CREATE TABLE tracks_by_word ( word PRIMARY KEY, paths )")
data = [ (word, json.dumps(paths)) for word, paths in d.items() ]
cur.executemany("INSERT INTO tracks_by_word ( word, paths ) VALUES ( ?, ? )", data )
con.commit()
con.close()
Find
The list of filenames is made by
find . -type f | grep -P '(mp3|m4a|wav|flac)$' > music.index.txt