【Android】AndroidでHLSストリーミング再生
はじめに
HLSをAndroidで受け取ってメディアプレイヤー再生したときの覚書き
メディアの再生にはandroidxのmedia3がメディアプレイヤー含め、かんたんに実装できそうだったのでこれを使った
ローカルのwebサーバー(flask)からhlsをダウンロードしてAndroidアプリ上のメディアプレイヤーから再生できることを確認した
hlsファイルの作成方法やファイル形式については、ここでは言及しないが、Androidが対応したものを使用するように注意する
実装
はじめにbuild.gradleにandroidxのmedia3への依存関係を追加する
dependencies {
implementation 'androidx.media3:media3-exoplayer:1.3.1'
implementation 'androidx.media3:media3-exoplayer-hls:1.3.1'
implementation 'androidx.media3:media3-exoplayer-workmanager:1.3.1'
implementation "androidx.media3:media3-exoplayer-dash:1.3.1"
implementation "androidx.media3:media3-ui:1.3.1"
}
AndroidManifestはネットワーク関連の権限を追加しておく
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
ここは必要に応じてだが、今回はローカルのwebサーバー上のhlsファイルを参照したかったので、下記のnetwork_security_config.xmlを作成してres/xmlに置いておく
Androidはデフォルトではhttpアクセスを許可していないらしく、このようなファイルが必用だった(今回はローカルサーバーでテストだけ行いたく、https設定が面倒だったのでこのように設定した)
ちゃんとやりたい人はファイルへのアクセスはhttpsを推奨
(おそらくhttpsの場合はこちらは不要)
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
メインのActivity実装コードは最後に載せておく
自分の場合は補足に記載したようなflaskのwebサーバーを立てていたので、
コード内の下記の箇所でアドレスとファイル名を指定してやればローカルのm3u8ファイルを参照してくれる
Uri hlsUri = Uri.parse("http://<your_address>:8000/video/<filename>.m3u8");
以下、コード全体
public class MainActivity extends AppCompatActivity {
public PlayerView playerView;
@OptIn(markerClass = UnstableApi.class)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExoPlayer player = new ExoPlayer.Builder(this).build();
playerView = findViewById(R.id.videoPlayer);
player = new ExoPlayer.Builder(this).build();
playerView.setPlayer(player);
// HTTPデータソースファクトリを作成
Factory dataSourceFactory = new Factory(this);
// HLSメディアソースを作成
Uri hlsUri = Uri.parse("http://<your_address>:8000/video/<filename>.m3u8");
MediaItem mediaItem = MediaItem.fromUri(hlsUri);
@OptIn(markerClass = UnstableApi.class) HlsMediaSource hlsMediaSource = new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem);
// プレイヤーにメディアソースを設定
player.setMediaSource(hlsMediaSource);
player.prepare();
player.play();
}
}
ちなみにレイアウトはメディアプレイヤーのみだが、こんな感じで記載した
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.media3.ui.PlayerView
android:id="@+id/videoPlayer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:keepScreenOn="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
補足
今回はpython flaskを使ってかんたんにローカルにwebサーバーを立てて、AndroidStudioの仮想端末にhlsを配信した
一応、こちらのコードも載せておく
※アドレスは(0.0.0.0などではなく)実際のアドレスを設定した
from flask import Flask, send_from_directory, render_template
import os
app = Flask(__name__)
# ビデオファイルが保存されているディレクトリ
VIDEO_DIR = '/path/to/your/directory'
@app.route('/video/<path:filename>')
def stream_video(filename):
return send_from_directory(VIDEO_DIR, filename)
if __name__ == '__main__':
app.run(host='<your_address>', port=8000)
Discussion