C# .m3u .m3u8 プレイリスト内から得た相対ファイルパスを(も)絶対パス形式にしたかった

公開日:2019-03-11
最終更新:2019-03-11

経緯とか

この規格の仕様とかって無いのかなーと思って調べたら、それっぽい情報がwikiにありました。

Wikipedia - M3U (日本語訳版) によると

正式な仕様は存在せず対応状況はまちまちである

との事 …orz
※ 今回 #EXTINF については省きます。

メディアファイルとして存在しうるpath

プレイリストに書かれたファイルパスの種類は、いくつかに分類できます。

  • ルートパス(例えばC:\とか)から始まる絶対パス
  • ネットワーク上のパス
  • ストリーミングとしてのパス(URL)
  • プレイリストファイルの位置を起点とした相対パス

1~3は絶対パスと考えれば、まぁ同義かもしれません。
問題は相対パスです

プレイリスト自身が置かれているパスを得る

プレイリストに書いてあるすべての相対パスは 、そのプレイリストファイルの位置を起点とする
といったルールが確立されているようなので、
まずはプレイリストファイル自身が置かれている位置から、配置ディレクトリ位置を取り出しておきます

string CurrentDirectoryPath = System.IO.Path.GetDirectoryName(PathPlayListFile);
プレイリストファイルパス System.IO.Path.GetDirectoryName() で得られる結果
@”D:\More Music\Foo.m3u” @”D:\More Music”
@”C:\music\favorite.m3u8” @”C:\music”
@”C:\any\bgm.m3u” @”C:\any”
@”E:\music\playlist\rock.m3u8” @”E:\music\playlist”

記載されたメディアファイルパスからルートパスを調べる

次に、プレイリスト内に記載されているメディアファイル行から、
書かれているメディアファイルのルートパスが得られるかどうかを確認します

string PathRoot = System.IO.Path.GetPathRoot(PathExtinfMedia);

ここでは通常、変数PathRoot には @"c:\"@"d:\" といった値が入ることが期待されますが、
相対パスが与えられた場合はこれが取得できません。

逆に言えば、得られた文字列内に [a-zA-Z] が含まれているルートパスが得られた
…として、そのまま読み込めるメディアパスとして扱えるとの判断もできます

メディアパス System.IO.Path.GetPathRoot() で得られる結果
@”D:\More Music\Foo.mp3” @”D:\“
@”Alternative\Band - Song.mp3” @””
@”\any\sound.mp3” @”\“
@”..\..\music\Hoge.mp3” @””
@”http://example.com/streaming_song.mp3 @””

参考 (詳しい例が見られます)
curict.com - [C#][VB.NET]ファイルのパスから、ルートディレクトリを取得する

メディアの相対パスとプレイリストディレクトリ位置から、絶対パスを導く

先ほどの処理 System.IO.Path.GetPathRoot() でメディアファイルのルートパスが得られなかった場合は
予め System.IO.Path.GetDirectoryName() で得た、プレイリストファイルのディレクトリ位置と、
記載されている相対パスの2つから、新たにUriクラスを用いて、絶対パスを生成します

参考
DOBON.NET - 任意のディレクトリを基準にして相対パスから絶対パスを取得する

String TargetPlayListPath = @"C:\playlist\myplaylist.m3u";  
String CurrentDirectoryPath = System.IO.Path.GetDirectoryName(TargetPlayListPath);  
// @"C:\playlist" が得られる  

String ReadMediaFilePath = @"..\any\sound.mp3";  

Uri u1 = new Uri(CurrentDirectoryPath);  
Uri u2 = new Uri(u1, ReadMediaFilePath);  

Console.WriteLine(u2.LocalPath); // @"C:\any\sound.mp3"

雑な検証・変換メソッド

public static Hoge(String CurrentDirectoryPath , String ReadMediaFilePath){  

    string AbsolutePath = "";  

    //ルートパスが得られる場合  
    if (System.Text.RegularExpressions.Regex.IsMatch(System.IO.Path.GetPathRoot(ReadMediaFilePath), "[a-zA-Z]"))  
    {  
        AbsolutePath = ReadMediaFilePath;  
    }  
    //ルートパスが得られない場合  
    else  
    {  
        if (Uri.IsWellFormedUriString(ReadMediaFilePath, UriKind.Absolute))  
        {  
            AbsolutePath = ReadMediaFilePath;  
        }  
        else  
        {  
            Uri u1 = new Uri(CurrentDirectoryPath);  
            Uri u2 = new Uri(u1, ReadMediaFilePath);  
            AbsolutePath = u2.LocalPath;  
        }  
    }  
    //Console.WriteLine("算出前{0}", ReadMediaFilePath);  
    //Console.WriteLine("算出後{0}", AbsolutePath);  
    return AbsolutePath;  
}

例として、このような Hoge() メソッドを作り、

  • プレイリストの配置ディレクトリパス
  • プレイリスト内に記載されたメディアパス

をそれぞれ与えると、以下のような結果が返ってくると思います

Hoge(@"C:\playlist" , @"music.mp3");  
// @"C:\playlist\music.mp3"  

Hoge(@"C:\playlist" , @"..\sound.wav");  
// @"C:\sound.wav"  

Hoge(@"D:\music" , @"\fooArtist\01_title.m4a");  
// @"D:\music\fooArtist\01_title.m4a"  

Hoge(@"D:\media\playlist" , @"C:\My Music\rockband\title\01_music.mp3");  
// @"C:\My Music\rockband\title\01_music.mp3"  

Hoge(@"D:\media\netradio" , @"http://example.com/streaming_song.mp3");  
// @"http://example.com/streaming_song.mp3"

例外などは考えていませんし、運用レベルで組むならプレイリストのパス自体は、
クラスのフィールドに持たせておいたほうが良さそうな気がします。

記事が少しでもいいなと思ったらクラップを送ってみよう!
18
+1
ひげさんのチラ裏だったりカンニングペーパーだったり学習ノートだったりする所です。

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする