我正在为需要流式传输AAC音频流的客户端开发应用程序。不幸的是,我无法对服务器上的流格式做任何事情。我正在使用Android,并发现Android的媒体播放器不支持原始AAC流(这是我得到的)。我在Google Code上发现了一个支持它的项目(我用流测试了它),但它是GPL,但对我的客户端不起作用。我对这类事情没有多少经验,如果我的想法不是很好,请原谅我。我知道Android 可以播放AAC编码的内容,如果它是在MP4包装器中,所以我考虑过在客户端动态创建MP4包装器,或者甚至只是在一些转换为另一种格式苍蝇这些合理的选择吗?有人有更好的建议吗?
提前致谢!
编辑要改写,是否可以实时将来自Web服务器的原始AAC流放入MP4容器中?如果是的话,是否有人知道有关资源来帮助我完成这个过程?
答案 0 :(得分:3)
我想知道你是否想出过这个问题的解决方案?我处于类似的情况。我们有一个生成AAC文件的Web服务,虽然不是原始的,但它们有ADTS头。 Android 2.2无法播放这些文件,虽然android 2.1可以,奇怪的是。这似乎是一个问题,根据Android切换到stagefright库以进行2.2中的媒体播放。
当包装在MP4容器中时,AAC文件可以正常播放。我们使用FAAC很容易在服务器端完成此任务(我意识到这对您的情况没有帮助)。我们仍在调查使用mp4容器的许可问题。这需要特许权使用费吗?
要回答我自己的问题......律师已确认使用mp4容器作为AAC文件不需要许可。
答案 1 :(得分:1)
我在谷歌的4个方案中试过 ACCDECODER 它运行良好。我找到了它,在2天内我就能做到! :)我找到它并在最后 Google I / O 2017
上看到了它我可以建议使用 EXOPLAYER INSTEAD MEDIAPLAYER 。这是一种更好,更好的方式。我使用MediaPlayer时遇到了同样的问题,但不久前我发现Exoplayer,现在我没有问题播放音频流Acc,mp3,mpeg等我可以给一些链接来检查它。
ExoPlayer是一个开源项目,不属于Android框架,与Android SDK分开发布。 ExoPlayer的标准音频和视频组件基于Android的MediaCodec API构建,该API在Android 4.1(API级别16)中发布。由于ExoPlayer是一个库,因此您可以通过更新应用程序轻松利用新功能。
ExoPlayer 支持MediaPlayer不支持的基于HTTP的动态自适应流媒体(DASH),SmoothStreaming和Common Encryption等功能。它的设计易于定制和扩展。
这与MediaPlayer几乎相同,因为Exoplayer从中扩展。您可以看到许多差异以及实现它的简单方法。如果您需要更多帮助,请告诉我:)
例如,你有这个:
Media Player mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource("http://your.url.com"); //add you url address
...
mediaPlayer.prepare();
mediaPlayer.start();
在Exoplayer中你需要它:
// 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示例代码:
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();
}
}
这是一个简短的例子,如果您正在寻找其他东西或需要更多帮助让我知道!我在这里!我想提供帮助,因为我知道当你在Google搜索和搜索以及它出现的任何内容时的感觉! :)小心!!