Exoplayer library seems so complex for me. Can anyone help me how to stream radio station url using exoplayer library? I tried with MediaPlayer , it works fine but it took so much time to prepare. Here is what I tried.
exoPlayer = ExoPlayer.Factory.newInstance(RENDERER_COUNT);
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
DataSource dataSource = new DefaultUriDataSource(getApplicationContext(), null, userAgent);
Mp3Extractor extractor = new Mp3Extractor();
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
uri, dataSource, extractor, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
exoPlayer.prepare(audioRenderer);
exoPlayer.setPlayWhenReady(true);
I don't understand how to get userAgent and what is meaning of it?
Here is a nice description of what a user agent is:
user agent
Also here the definition of how a user agent should look like:
structure of user agent header
Here you can see how your browser's user agent looks like:
http://whatsmyuseragent.com/
To put it simply you can create your user agent like this:
"YourAppName/VersionCode"
Finally a description of how to use ExoPlayer to stream mp3:
Stream mp3 with ExoPlayer
In this example it is a local mp3 though, but the only difference should be the url of the mp3 and the missing user agent.
Hope this helps!
This is the simplest way to stream m3u8 files using ExoPlayer Lib.
check this code and don't forget to change the URL to yours and also change the content type as the blew code
hope to help
https://github.com/karim23/SimpleStreamPlayer/tree/master
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getApplicationContext();
setContentView(R.layout.activity_main);
//change the live streaming URL with yours.
contentUri = /*"Your mp3 URL.."*/;
// contentType = DemoUtil.TYPE_MP3;
final Intent intent = new Intent(context, VideoPlayerActivity.class).setData(Uri.parse(contentUri))
.putExtra(VideoPlayerActivity.CONTENT_ID_EXTRA, -1)
//Change the type according to the live streaming extension.
.putExtra(VideoPlayerActivity.CONTENT_TYPE_EXTRA, DemoUtil.TYPE_MP3);
liveStreamingTv =(TextView)findViewById(R.id.mainActivity_liveStreamingTv);
liveStreamingTv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivity(intent);
}
});
}
It was problem with codec, exoPlayer doesn't support aac+
Related
I use the following code to play a music stream through ExoPlayer:
exoPlayer = ExoPlayer.Factory.newInstance(numRenderers, minBufSize, maxBufSize);
String url = Helper.getPr().getString("url", "http://mp3.nashe.ru:80/ultra-128.mp3");
Uri uri = Uri.parse(url);
Log.i(TAG, "Going to open " + url);
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
DataSource dataSource = new DefaultUriDataSource(getApplicationContext(), USER_AGENT);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
exoPlayer.addListener(this);
exoPlayer.sendMessage(audioRenderer, MediaCodecAudioTrackRenderer.MSG_SET_VOLUME, volume);
exoPlayer.prepare(audioRenderer);
exoPlayer.setPlayWhenReady(true);
I can't find any info on how to get metadata like artist and name of the current song. Is it possible to get the metadata and if yes, how?
Thanks a lot.
There are many types of metadata in many types of media, It's depending on your stream. But currently Exoplayer itself, only parse metadata from HLS streams (HTTP Live Streaming) they get ID3 data from the stream.
As you can see on there github repository issue,this is the current state of metadata in Exoplayer lib (August 2015):
https://github.com/google/ExoPlayer/issues/704
If it's your stream case, I will recommend you to download the Exoplayer demo on github (https://github.com/google/ExoPlayer/tree/release-v2/demos).
One of the examples in the demo display stream ID3 metadata on LogCat.
If it's not your case, nothing will help you in ExoPlayer lib right now.
But there is an alternative solution, which I have used for a radio stream application, and it work well:
IcyStreamMeta to get meta data from online stream radio :
Getting metadata from SHOUTcast using IcyStreamMeta
but not sure it will work with simple mp3 file.
I am late But with Exoplayer-2. You can use an extension created by #saschpe. https://github.com/sandeeprana011/android-exoplayer2-ext-icy
For example see this app: https://play.google.com/store/apps/details?id=com.zilideus.jukebox_new
gradle
implementation 'saschpe.android:exoplayer2-ext-icy:1.0.1'
So it includes an Extra Header "Icy-Metadata" with value 1
and on the response, it extracts the metadata from the stream data.
Usage:
IcyHttpDataSourceFactory factory = new IcyHttpDataSourceFactory.Builder(Util.getUserAgent(this, getResources().getString(R.string.app_name)))
.setIcyHeadersListener(this)
.setIcyMetadataChangeListener(this).build();
DefaultDataSourceFactory datasourceFactory = new DefaultDataSourceFactory(getApplicationContext(), null, factory);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Factory(datasourceFactory)
.setExtractorsFactory(new DefaultExtractorsFactory())
.createMediaSource(uri);
Exo.resetPlayer();
Exo.getPlayer(this).prepare(mediaSource);
In the case of Icy metadata, exoplayer has built in support as of version 2.10. see: https://stackoverflow.com/a/56333429/1898380
You probably should use MediaMetadataRetriever
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(getActivity(), uri);
String artist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
You could use the follow code to do that(Maybe you should download the mp3 file first):
MediaMetadataRetriever metaRetriver = new MediaMetadataRetriever();
metaRetriver.setDataSource("LOCAL MP3 FILE PATH");
byte[] picArray = metaRetriver.getEmbeddedPicture();
Bitmap songImage = BitmapFactory .decodeByteArray(picArray, 0, picArray.length);
String albumName = metaRetriver .extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
String artistName = metaRetriver .extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
String songGenre = metaRetriver .extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE));
source:http://mrbool.com/how-to-extract-meta-data-from-media-file-in-android/28130#ixzz3s8PUd9E7
I'm traying to use ExoPlayer for playback video over http. And I want to save video after video was loaded and play it from cache. How Do implement cache and playback from cache? Can give me any samples.
You use cacheDataSource created using cache and dataSource. This cacheDataSource is then used by ExtractorSampleSource.Below is the code for audioRenderer, similarly can be done for videoRender; passing to exoplayerInstance.prepare(renderers).
Cache cache = new SimpleCache(mCtx.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 10));
DataSource dataSource = new DefaultUriDataSource(mCtx, "My Player");
CacheDataSource cacheDataSource = new CacheDataSource(cache, dataSource, false, false);
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
ExtractorSampleSource extractorSampleSource = new ExtractorSampleSource(trackURI, cacheDataSource, allocator, BUFFER_SEGMENT_COUNT*BUFFER_SEGMENT_SIZE, new Mp3Extractor());
MediaCodecAudioTrackRenderer audioTrackRenderer = new MediaCodecAudioTrackRenderer(extractorSampleSource);
What protocol are you using mpeg-dash or plain http.
You can override HttpDataSource and write incoming bytes to a file and when playing again check if file exists at the desired location and change the InputStream fed to the player from your file instead of HttpDataSource.
I use exoplayer with this library:
https://github.com/danikula/AndroidVideoCache
It helps you cache the video from a resource (URL, file)...
This is my sample code:
String mediaURL = "https://my_cool_vid.com/vi.mp4";
SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(getContext());
HttpProxyCacheServer proxyServer = HttpProxyCacheServer.Builder(getContext()).maxCacheSize(1024 * 1024 * 1024).build();
String proxyURL = proxyServer.getProxyUrl(mediaURL);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(),
Util.getUserAgent(getContext(), getActivity().getApplicationContext().getPackageName()));
exoPlayer.prepare(new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(proxyURL)););
This library is easy to use: https://github.com/danikula/AndroidVideoCache. You just need to have the initialization code found in the repo in an appcontroller.
For those using mediaitem, this is what you can do:
exoPlayer = new SimpleExoPlayer.Builder(context).build();
holder.exoPlayerView.setPlayer(exoPlayer);
HttpProxyCacheServer proxyServer = AppController.getProxy(context);
String streamingURL = shortVideosRecommendationsArrayList.get(holder.getAbsoluteAdapterPosition()).getStreamingURL();
String proxyURL = proxyServer.getProxyUrl(streamingURL);
MediaItem mediaItem = MediaItem.fromUri(proxyURL);
exoPlayer.setMediaItem(mediaItem);
exoPlayer.setRepeatMode(exoPlayer.REPEAT_MODE_ALL);
exoPlayer.prepare();
exoPlayer.setPlayWhenReady(true);
Can we play flv stream videos in Android without using WebView, it's too slow? I mean play .flv video directly from url. Any ideas? VideoView now work with the .flv link.
I got it to work using this code. You can play it local from your device or stream it from online. You have to drag an instance of the FLV COMPONENT in your movie and then just delete it from the stage to it remains in your library.
var myVideo:FLVPlayback = new FLVPlayback();
myVideo.source = "content/video/BeauIntro.flv"; // CHANGE THIS TO YOUR FLV
myVideo.autoPlay = true;
// I am choosing to load the flv into an empty movie but you don't have to.
var my_mc:MovieClip = new MovieClip();
addChild(my_mc);
/// These are important because it can mess up position with out it.
myVideo.align = StageAlign.TOP_LEFT;
myVideo.scaleMode = VideoScaleMode.EXACT_FIT;
// Setting the video to the screen size of device
myVideo.width = stage.stageWidth;
myVideo.height = stage.stageHeight;
// Adding my FLV into my empty movie.
my_mc.addChild(myVideo);
//Setting the empty Movie Clip for the video to the screen size of device
my_mc.width = stage.stageHeight;
my_mc.height = stage.stageHeight;
/// This will run when the video stops
myVideo.addEventListener(fl.video.VideoEvent.COMPLETE, VideoStopped);
function VideoStopped(e:Event):void
{
myVideo.stop();
myVideo.visible = false; /// I wanted it to not be seen after playing.
trace("stopped");
myVideo.removeEventListener(fl.video.VideoEvent.COMPLETE, VideoStopped);
}
try this:
String url=your url here;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "flv-application/octet-stream");
startActivity(intent);
I'm working on an app for a client that requires streaming of an AAC audio stream. Unfortunately, there's nothing I can do about the stream format on the server. I'm working on Android and have discovered that Android's media player does not support raw AAC streams (which is what I'm getting). I found a project on Google Code that supports it (I tested it with the stream) but it's GPL'ed and that doesn't work for my client. I don't have much experience with this sort of thing so forgive me if my ideas aren't great. I know Android can play AAC encoded content if it is in an MP4 wrapper so I had thought about creating an MP4 wrapper on the fly on the client-side or perhaps even just doing some conversion to another format on the fly. Are these reasonable options? Does anybody have better suggestions?
Thanks in advance!
Edit To rephrase, is it possible to put a raw AAC stream from a web server in an MP4 container in real time? If so, does anybody know of resources to help me with the process?
I'm wondering if you ever came up with a solution for this problem? I'm in a similar situation. We have a web service generating AAC files, though not raw, they have the ADTS header. Android 2.2 can't play these files, though android 2.1 can, oddly enough. It seems to be a problem rooted to android switching to stagefright libraries for media playback in 2.2.
The AAC files do play fine when wrapped in an MP4 container. We've accomplish this on the server side very easily using FAAC (I realize this doesn't help you in your situation). We are still investigating licensing issues with using an mp4 container though. Does this require royalties?
To answer my own question...a lawyer has confirmed that using an mp4 container for an AAC file does not require licensing.
I TRIED ACCDECODER by Google for 4 motnhs it did work well. I found it and in 2 days I could did it works! :) I found it and saw it on the last Google I/O 2017
I can suggest to use EXOPLAYER INSTEAD MEDIAPLAYER. It is a better and improve way. I had the same problem using just MediaPlayer, but short time ago I found Exoplayer, now I do not have problem to Play audio streaming Acc, mp3, mpeg, etc. I can give a couple links to check it.
ExoPlayer is an open source project that is not part of the Android framework and is distributed separately from the Android SDK. ExoPlayer’s standard audio and video components are built on Android’s MediaCodec API, which was released in Android 4.1 (API level 16). Because ExoPlayer is a library, you can easily take advantage of new features as they become available by updating your app.
ExoPlayer supports features like Dynamic adaptive streaming over HTTP (DASH), SmoothStreaming and Common Encryption, which are not supported by MediaPlayer. It's designed to be easy to customize and extend.
This is almost the same like MediaPlayer because Exoplayer extend from it. You can see a lot of differences and an easy way to implement it. If you need more help let me know :)
For example you have this:
Media Player mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource("http://your.url.com"); //add you url address
...
mediaPlayer.prepare();
mediaPlayer.start();
In Exoplayer you need it:
// Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
//Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
ExoPlayer example code:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private SimpleExoPlayerView simpleExoPlayerView;
private SimpleExoPlayer player;
private ExoPlayer.EventListener exoPlayerEventListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG,"portrait detected...");
setContentView(R.layout.activity_main);
// 1. Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory);
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
//Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
//CHOOSE CONTENT: Livestream links may be out of date so find any m3u8 files online and replace:
//VIDEO FROM SD CARD:
// String urimp4 = "/FileName.mp4";
// Uri mp4VideoUri = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath()+urimp4);
//yachts livestream m3m8 file:
Uri mp4VideoUri =Uri.parse("http://your.url.com");
//Random livestream file:
// Uri mp4VideoUri =Uri.parse("http://your.url.com");
//Sports livestream file:
// Uri mp4VideoUri =Uri.parse("http://your.url.com");
// Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
//Produces DataSource instances through which media data is loaded.
// DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "exoplayer2example"), bandwidthMeterA);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "exoplayer2example"), bandwidthMeterA);
//Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
//This is the MediaSource representing the media to be played:
//FOR SD CARD SOURCE:
// MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri, dataSourceFactory, extractorsFactory, null, null);
//FOR LIVESTREAM LINK:
MediaSource videoSource = new HlsMediaSource(mp4VideoUri, dataSourceFactory, 1, null, null);
final LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
// Prepare the player with the source.
player.prepare(loopingSource);
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onLoadingChanged(boolean isLoading) {
Log.v(TAG,"Listener-onLoadingChanged...");
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.v(TAG,"Listener-onPlayerStateChanged...");
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
Log.v(TAG,"Listener-onTimelineChanged...");
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Log.v(TAG,"Listener-onPlayerError...");
player.stop();
player.prepare(loopingSource);
player.setPlayWhenReady(true);
}
#Override
public void onPositionDiscontinuity() {
Log.v(TAG,"Listener-onPositionDiscontinuity...");
}
});
player.setPlayWhenReady(true);
}//End of onCreate
#Override
protected void onStop() {
super.onStop();
Log.v(TAG,"onStop()...");
}
#Override
protected void onStart() {
super.onStart();
Log.v(TAG,"onStart()...");
}
#Override
protected void onResume() {
super.onResume();
Log.v(TAG,"onResume()...");
}
#Override
protected void onPause() {
super.onPause();
Log.v(TAG,"onPause()...");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG,"onDestroy()...");
player.release();
}
}
It was a short example, If you are looking for something else or need more help let me know! I am here! I would like to help because I know how it feels when you are googling and searching and anything it is showing up! :) Take care!!
As I understand it, Android will only play AAC format audio if it's encoded as MPEG-4 or 3GPP.
I'm able to play AAC audio encoded as M4A when it's local to the app, but it fails when obtaining it from a server.
The following works, as the m4a file is held locally in the res/raw directory.
MediaPlayer mp = MediaPlayer.create(this, R.raw.*file*);
mp.start();
The following doesn't work. (But does with MP3's).
Uri uri = Uri.parse("http://*example.com*/blah.m4a");
MediaPlayer mp = MediaPlayer.create(this, uri);
mp.start();
Can anyone shed any light on why it fails when the m4a audio file is not local?
Here's (some of) the error...
ERROR/PlayerDriver(542): Command PLAYER_INIT completed with an error or info UNKNOWN PVMFStatus
ERROR/MediaPlayer(769): error (200, -32)
WARN/PlayerDriver(542): PVMFInfoErrorHandlingComplete
DEBUG/MediaPlayer(769): create failed:
DEBUG/MediaPlayer(769): java.io.IOException: Prepare failed.: status=0xC8
DEBUG/MediaPlayer(769): at android.media.MediaPlayer.prepare(Native Method)
DEBUG/MediaPlayer(769): at android.media.MediaPlayer.create(MediaPlayer.java:530)
DEBUG/MediaPlayer(769): at android.media.MediaPlayer.create(MediaPlayer.java:507)
...
I'm targeting SDK 1.6.
This work-around allows you to play M4A files from the net (and AAC files in other containers such as MP4 & 3GP). It simply downloads the file and plays from the cache.
private File mediaFile;
private void playAudio(String mediaUrl) {
try {
URLConnection cn = new URL(mediaUrl).openConnection();
InputStream is = cn.getInputStream();
// create file to store audio
mediaFile = new File(this.getCacheDir(),"mediafile");
FileOutputStream fos = new FileOutputStream(mediaFile);
byte buf[] = new byte[16 * 1024];
Log.i("FileOutputStream", "Download");
// write to file until complete
do {
int numread = is.read(buf);
if (numread <= 0)
break;
fos.write(buf, 0, numread);
} while (true);
fos.flush();
fos.close();
Log.i("FileOutputStream", "Saved");
MediaPlayer mp = new MediaPlayer();
// create listener to tidy up after playback complete
MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// free up media player
mp.release();
Log.i("MediaPlayer.OnCompletionListener", "MediaPlayer Released");
}
};
mp.setOnCompletionListener(listener);
FileInputStream fis = new FileInputStream(mediaFile);
// set mediaplayer data source to file descriptor of input stream
mp.setDataSource(fis.getFD());
mp.prepare();
Log.i("MediaPlayer", "Start Player");
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
}
I tried it too but I could not find out the solution!
At the last Google I/O I saw something that helped me a lot. It is Extending from MediaPlayer and improve a lot of things! Take a look.
EXOPLAYER CAN HELP YOU A LOT
Check this part of the example:
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
private static final int BUFFER_SEGMENT_COUNT = 256;
...
// String with the url of the radio you want to play
String url = getRadioUrl();
Uri radioUri = Uri.parse(url);
// Settings for exoPlayer
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
String userAgent = Util.getUserAgent(context, "ExoPlayerDemo");
DataSource dataSource = new DefaultUriDataSource(context, null, userAgent);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
radioUri, dataSource, allocator, BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
// Prepare ExoPlayer
exoPlayer.prepare(audioRenderer);
EXOPLAYER- I can play anything from streamings (video and audio)!
LET ME KNOW IF YOU NEED HELP TO IMPLEMENT IT! :)
This is a wild shot in the dark, but I have seen similar behavior with the flash player where it actually ignores the file name and only relies on the MIME type sent by the server. Any idea what headers are being sent down from example.com? You might want to try wrapping your blah.m4a in a page that can set the headers and then stream the binary data. Give these types a shot and the community would appreciate a confirmation of what works:
audio/mpeg
audio/mp4a
audio/mp4a-latm
audio/aac
audio/x-aac
I found that if you record the audio file on Android with the following properties, you are then able to play it on your server. It also plays well in the HTML Audio Element, however only on Firefox at the moment. This may change in the future.
Android (JAVA):
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setAudioChannels(1);
mediaRecorder.setOutputFile(filePath);
HTML:
<audio id="audioMediaControl" controls src="yourfile.m4a"> Your browser does not support the audio element. </audio>
try --
1) MP.prepareAsync()
2) onPrepared() { mp.start() }