我使用套接字作为MediaPlayer的代理,因此可以在将mp3音频写入套接字之前下载并解密。 这类似于NPR新闻应用程序中显示的示例,但是我将其用于所有Android版本2.1-4 atm。
NPR StreamProxy代码-[http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java]
我的问题是,对于2.1-2.3而言,播放速度很快,但是在Android 4.0 ICS中,MediaPlayer在触发onPrepared侦听器之前会缓冲太多数据。
在onPrepared()之前写入Socket OutputStream的数据量示例:
在具有2.3.4的SGS2上-约133920字节后的onPrepared()
在使用4.0.4的Nexus S上-约961930字节后的onPrepared()
这也发生在Galaxy Nexus上。
奇怪的是4.0仿真器不像4.0设备那样缓冲太多的数据。 任何人在ICS上遇到MediaPlayer的类似问题?
编辑
这是代理写入套接字的方式。 在此示例中,它是从文件加载的CipherInputStream中获得的,但是从HttpResponse中加载它的情况相同。
final Socket client = (setup above)
// encrypted file input stream
final CipherInputStream inputStream = getInputStream(file);
// setup the socket output stream
final OutputStream output = client.getOutputStream();
// Writing the header
final String httpHeader = buildHttpHeader(file.length());
final byte[] buffer = httpHeader.getBytes("UTF-8");
output.write(buffer, 0, buffer.length);
int writtenBytes = 0;
int readBytes;
final byte[] buff = new byte[1024 * 12]; // 12 KB
while (mIsRunning && (readBytes = inputStream.read(buff)) != -1) {
output.write(buff, 0, readBytes);
writtenBytes += readBytes;
}
output.flush();
output.close();
在音频之前写入MediaPlayer的HTTP标头。
private String buildHttpHeader(final int contentLength) {
final StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\r\n");
sb.append("Content-Length: ").append(contentLength).append("\r\n");
sb.append("Accept-Ranges: bytes\r\n" );
sb.append("Content-Type: audio/mpeg\r\n");
sb.append("Connection: close\r\n" );
sb.append("\r\n");
return sb.toString();
}
我四处寻找替代实现,但是由于我已经加密了音频并且MediaPlayer不支持InputStreams作为数据源,所以我唯一的选择(我认为..)是使用诸如此类的代理。
同样,这在Android 2.1-2.3上运行良好,但在ICS中,MediaPlayer在播放之前会缓冲大量此类数据。
编辑2:
进一步的测试表明,一旦升级到Android 4.0.3,这在SGS2上也是一个问题。 因此,似乎MediaPlayer的缓冲实现在4.0中已发生了显着变化。 由于API无法提供任何更改行为的方式,因此令人沮丧。
编辑3:
已创建Android错误。 请添加评论并在其中加注星标[http://code.google.com/p/android/issues/detail?id=29870]
编辑4:
我的播放代码相当标准。.我在onPrepared()方法中对MediaPlayer进行了start()调用。
mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mCurrentPlayer.setDataSource(url);
mCurrentPlayer.prepareAsync();
仅使用prepare()和ajacian81的推荐方法进行了尝试,但无济于事。
我应该补充一点,最近有一位Google员工回覆了我的问题,并确认ICS(用于HD内容)的缓冲区大小是有意增加的。 已要求API开发人员添加在MediaPlayer上设置缓冲区大小的功能。
尽管我认为这个API更改请求在我来之前就已经存在了,所以我不建议任何人屏住呼吸。
我可以使用ffmpeg将两个音频mp3文件叠加/缩混为一个mp3输出文件吗?
我想编写一个简单的C#应用程序来监视输入音频,并为我提供每分钟的当前心跳(滚动平均值)。
我看过这篇关于gamedev的文章,那绝对没有帮助。 我经历了一下,试图实现他正在做的事情,但是那没有用。
我知道必须有很多解决方案,因为很多DJ软件都可以做到这一点,但是我没有运气去找到任何开源库或自己做的说明。
我有一些长时间运行的脚本,需要休息才能继续输入/交互,但是当我切换到另一个窗口时,我想(通过声音)收到任务已完成且正在等待输入的通知。
我希望能够播放音频剪辑(* .mp3,*。ogg等),但是不管唯一的解决方案是否是使PC扬声器发出哔哔声,都不会在意。
有任何想法吗? 我可以安装任何CLI实用程序,可以播放声音,然后可以在需要时执行这些声音。
仅供参考:我的系统正在运行WinXP Pro。
更新:!! 我的Windows>控制面板>声音>默认提示音:设置为(无)。 rr ...
问题解决了。
AVPlayer的文档规定以下内容:
[The]播放器可以很好地处理本地和远程媒体文件
但是,AVAudioPlayer的文档指出以下内容:
Apple建议您使用此类进行音频播放,除非您要播放从网络流捕获的音频
对于我正在做的工作,我需要一些AVAudioPlayer的功能,但是我的所有音频都正在流式传输。 我需要AVAudioPlayer中AVPlayer没有的主要内容是“播放”属性。 如果没有该属性,则很难构建播放器用户界面。
那么,AVPlayer和AVAudioPlayer有什么区别,使后者不适合网络流传输? 有没有办法从AVAudioPlayer提供的AVPlayer中获取一些信息,例如“播放”属性?
我似乎在SDK中找不到如何以编程方式感应iPhone上的静音按钮/开关。 当我的应用播放背景音乐时,它可以正确响应音量按钮,而无需我遵循任何代码,但是当我使用静音开关时,它会一直播放。
如何测试静音的位置?
(注意:我的程序有其自己的静音开关,但我希望物理开关可以覆盖该开关。)
我喜欢思考一切如何实现并以数字表示。 例如,纯文本由类似ASCII的代码表示,图像由RGB值表示。 这些是表示文本和图像的最简单方法。
用数字表示音频的最简单方法是什么? 我想学习如何编写适用于音频的程序,并认为这将是一个很好的开始。 不过,我似乎在互联网上找不到任何好的解释。
我该如何获取MP3并将语音转换为文本?
我从会议和会议中得到了一些录音笔记(录音中只有一个声音,就是我的声音)。 我认为使用语音转文本工具将文本转换为文本,而不是简单地手动转录会更容易且在智力上也很有趣。 我知道那里有技术,特别是对于使用Asterisk和Podcasts的VoIP应用程序,但是它们是什么,我该如何使用它们?
NSDictionary* fileAttributes =
[[NSFileManager defaultManager] attributesOfItemAtPath:filename
error:nil]
从文件属性键中,您可以获取日期,大小等。但是,如何获取持续时间呢?
如您所见,我正在流式传输音频广播。 但是,当我按下主页按钮并退出应用程序时,流媒体播放停止,或者我听不到声音。 如何继续在后台流式传输并从锁定屏幕收听?
ViewController.Swift
import UIKit
import AVFoundation
import MediaPlayer
import GoogleMobileAds
class ViewController: UIViewController, GADInterstitialDelegate {
@IBOutlet weak var exitMapButton: UIButton!
@IBOutlet weak var radarMap: UIWebView!
var interstitial: GADInterstitial!
func createAndLoadInterstitial() -> GADInterstitial {
var interstitial = GADInterstitial(adUnitID: "ca-app-pub-5378899862041789/2782958552")
interstitial.delegate = self
interstitial.loadRequest(GADRequest())
return interstitial
}
func getAd(){
if (self.interstitial.isReady)
{
self.interstitial.presentFromRootViewController(self)
self.interstitial = self.createAndLoadInterstitial()
}
}
@IBOutlet weak var ataturkButton: UIButton!
@IBOutlet weak var sabihaButton: UIButton!
@IBOutlet weak var esenbogaButton: UIButton!
@IBOutlet weak var weatherButton: UIButton!
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var webViewButton: UIButton!
var googleBannerView: GADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
}
class PlayerAv {
var audioLink: String?
var player: AVPlayer
init(link: String) {
self.audioLink = link
self.player = AVPlayer(URL: NSURL(string: link))
}
}
var myPlayer = PlayerAv(link: "http://www.liveatc.net/play/ltba.pls")
var setTowerState = ""
@IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Float(sender.value)
println(currentValue)
myPlayer.player.volume = currentValue
}
@IBAction func getWeatherWindow(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string: "http://www.aviationweather.gov/adds/metars/?station_ids=ltac&std_trans=standard&chk_metars=on&hoursStr=most+recent+only&chk_tafs=on&submitmet=Submit")!)
println("Directed to weather page")
}
@IBAction func changeToAtaturk() {
myPlayer.player.pause()
myPlayer = PlayerAv(link: "http://www.liveatc.net/play/ltba.pls")
myPlayer.audioLink == ""
println("\(myPlayer.audioLink!)--a")
playButton.setTitle("Pause", forState: UIControlState.Normal)
myPlayer.player.play()
setTowerState = "ataturk"
statusLabel.text = "Status: Playing, LTBA"
}
@IBAction func changeToEsenboga() {
myPlayer.player.pause()
myPlayer = PlayerAv(link: "http://www.liveatc.net/play/ltac.pls")
println("\(myPlayer.audioLink!)--a")
playButton.setTitle("Pause", forState: UIControlState.Normal)
myPlayer.player.play()
setTowerState = "esenboga"
statusLabel.text = "Status: Playing, LTAC"
}
@IBAction func changeToSabiha() {
myPlayer.player.pause()
myPlayer = PlayerAv(link: "http://www.liveatc.net/play/ltfj.pls")
println("\(myPlayer.audioLink!)--a")
playButton.setTitle("Pause", forState: UIControlState.Normal)
myPlayer.player.play()
setTowerState = "sabiha"
statusLabel.text = "Status: Playing, LTFJ"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func playButtonPressed(sender: AnyObject) {
toggle()
}
func toggle() {
if playButton.titleLabel?.text == "Play" {
playRadio()
println("Playing")
statusLabel.text = "Status: Playing"
} else {
pauseRadio()
println("Paused")
statusLabel.text = "Status: Paused"
}
}
func playRadio() {
myPlayer.player.play()
playButton.setTitle("Pause", forState: UIControlState.Normal)
}
func pauseRadio() {
myPlayer.player.pause()
playButton.setTitle("Play", forState: UIControlState.Normal)
}
}
我正在尝试使用图片数组和音频文件制作电影文件。 为了制作带有图片阵列的电影,我在这里使用了zoul的重要文章。 一切都太完美了,我的电影里有我的照片。 但是,当我尝试添加一些音轨时,会有很多问题。 为了理解我把我的代码:
当我调用此方法时,图片数组和歌曲文件已准备就绪:
-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size
{
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:documentsDirectoryPath];
for (NSString *tString in dirContents) {
if ([tString isEqualToString:@"essai.mp4"])
{
[[NSFileManager defaultManager]removeItemAtPath:[NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,tString] error:nil];
}
}
NSLog(@"Write Started");
NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path] fileType:AVFileTypeMPEG4
error:&error];
NSParameterAssert(videoWriter);
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:size.width], AVVideoWidthKey,
[NSNumber numberWithInt:size.height], AVVideoHeightKey,
nil];
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *audioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0] ,AVSampleRateKey,
[NSNumber numberWithInt: 1] ,AVNumberOfChannelsKey,
[NSNumber numberWithInt:192000],AVEncoderBitRateKey,
[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],AVChannelLayoutKey,
nil];
AVAssetWriterInput* videoWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
AVAssetWriterInput* audioWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeAudio
outputSettings:audioSettings] retain];
NSURL* fileURL = [[NSBundle mainBundle] URLForResource:@"Big_Voice_1" withExtension:@"caf"];
NSLog(@"%@",fileURL);
AVAsset *asset = [[AVURLAsset URLAssetWithURL:fileURL
options:nil] retain];
AVAssetReader *audioReader = [[AVAssetReader assetReaderWithAsset:asset error:&error] retain];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
sourcePixelBufferAttributes:nil];
AVAssetTrack* audioTrack = [asset.tracks objectAtIndex:0];
AVAssetReaderOutput *readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil];
[audioReader addOutput:readerOutput];
NSParameterAssert(videoWriterInput);
NSParameterAssert(audioWriterInput);
NSParameterAssert([videoWriter canAddInput:audioWriterInput]);
NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
audioWriterInput.expectsMediaDataInRealTime = NO;
videoWriterInput.expectsMediaDataInRealTime = YES;
[videoWriter addInput:audioWriterInput];
[videoWriter addInput:videoWriterInput];
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
//Video encoding
CVPixelBufferRef buffer = NULL;
//convert uiimage to CGImage.
int frameCount = 0;
for(int i = 0; i<20; i++)
{
buffer = [self pixelBufferFromCGImage:[[m_PictArray objectAtIndex:i] CGImage] andSize:size];
BOOL append_ok = NO;
int j = 0;
while (!append_ok && j < 30)
{
if (adaptor.assetWriterInput.readyForMoreMediaData)
{
printf("appending %d attemp %d\n", frameCount, j);
CMTime frameTime = CMTimeMake(frameCount,(int32_t) 10);
//CVPixelBufferPoolCreatePixelBuffer (kCFAllocatorDefault, adaptor.pixelBufferPool, &buffer);
append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
CVPixelBufferPoolRef bufferPool = adaptor.pixelBufferPool;
NSParameterAssert(bufferPool != NULL);
[NSThread sleepForTimeInterval:0.05];
}
else
{
printf("adaptor not ready %d, %d\n", frameCount, j);
[NSThread sleepForTimeInterval:0.1];
}
j++;
}
if (!append_ok) {
printf("error appending image %d times %d\n", frameCount, j);
}
frameCount++;
}
//Finish the session:
[videoWriterInput markAsFinished];
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
//Write all picture array in movie file.
int frameCount = 0;
for(int i = 0; i<[m_PictArray count]; i++)
{
buffer = [self pixelBufferFromCGImage:[[m_PictArray objectAtIndex:i] CGImage] andSize:size];
BOOL append_ok = NO;
int j = 0;
while (!append_ok && j < 30)
{
if (adaptor.assetWriterInput.readyForMoreMediaData)
{
printf("appending %d attemp %d\n", frameCount, j);
CMTime frameTime = CMTimeMake(frameCount,(int32_t) 10);
append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
CVPixelBufferPoolRef bufferPool = adaptor.pixelBufferPool;
NSParameterAssert(bufferPool != NULL);
[NSThread sleepForTimeInterval:0.05];
}
else
{
printf("adaptor not ready %d, %d\n", frameCount, j);
[NSThread sleepForTimeInterval:0.1];
}
j++;
}
if (!append_ok) {
printf("error appending image %d times %d\n", frameCount, j);
}
frameCount++;
}
//Finish writing picture:
[videoWriterInput markAsFinished];
我完成了在电影文件中写入图片的操作,并且想要在文件中复制音频,然后执行以下操作:
[audioReader startReading];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
[audioWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^
{
NSLog(@"Request");
NSLog(@"Asset Writer ready :%d",audioWriterInput.readyForMoreMediaData);
while (audioWriterInput.readyForMoreMediaData) {
NSLog(@"Ready");
CMSampleBufferRef nextBuffer = [readerOutput copyNextSampleBuffer];
if (nextBuffer) {
NSLog(@"NextBuffer");
[audioWriterInput appendSampleBuffer:nextBuffer];
}
}
}
];
[audioWriterInput markAsFinished];
[videoWriter finishWriting];
但是,音频文件的AssetWriterInput的状态始终为“否”。
我的问题:如何使用AVFoundation将音频添加到视频文件?
因此,请有人告诉我是否忘记某事或某事有误,可以帮助我。
非常感谢你
会是一件好事-我必须写一个脚本还是不能只是调整构建脚本来完成某些任务?
我的iPhone模拟器以某种方式无法播放声音。 首先,我正在使用AudioServicesPlaySystemSound()
开发的一个应用程序停止工作。.我花了一些时间对此进行调试,但是当我在设备上运行该应用程序时,声音仍在iPhone上运行。 我在其他iPhone应用程序(例如示例“崩溃着陆”应用程序)中得到了相同的结果。
我在模拟器或Xcode首选项的任何地方都找不到声音设置。 我尝试通过“重置内容和设置”菜单项重置模拟器无济于事。
我发现Android MediaPlayer准备使用不同流进行实时流播放所需的时间存在很大差异。
硬数据
我在prepareAsync()和onPrepared(MediaPlayer mp)回调之间添加了日志记录,并分别测试了几个流。 每个流的时间非常一致(+/-一秒),结果如下:
测试是在3G连接(约1100 Kbps)和Android 2.3.4的Nexus S上进行的。
播放非流式MP3音频文件不是问题。
以下是我如何播放视频流的摘要:
准备MediaPlayer:
...
mediaPlayer.setDataSource(playUrl);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync();
...
然后在onPrepared(MediaPlayer mp)中:
mediaPlayer.start();
为什么准备一些流而不用准备其他流需要这么长时间? 以上数据似乎表明它可能是基于已缓冲的数据量而不是缓冲的音频内容的持续时间。 真的可以吗?
更新:我已经在具有Android 1.6、2.2和2.3.4的物理设备以及具有1.6、2.1、2.2、2.3.1和2.3.3的模拟器上测试了实时流。 我只看到2.3.3和2.3.4的长时间延迟。 旧版本将在5秒钟内开始播放。
我的android手机中有一个mp3文件,让它在我的sdcard中的某个地方是xyz.mp3。如何通过我的应用程序播放它?
我试图将MP3剪辑在两个起点之间,例如从10秒开始到16秒(6秒的时间间隔)结束。
我正在使用此命令:
output.mp3
结果output.mp3
包含我指定的6秒,然后是8或9秒的空音频。 我的命令有问题吗?
编辑:
ffmpeg -ss 10 -to 16 -i input.mp3 output.mp3
说-t is not an input option, keeping it for the next output; consider fixing your command line.
,并给了我一个文件,该文件从10s开始有8秒钟的音频,然后有9或10秒钟的静音。
ffmpeg -ss 10 -to 16 -i input.mp3 output.mp3
产生的文件长度是原始文件长度的两倍-基本上相同的音频文件会再次重复。\
测试输出:
我使用的是Quicktime,并且最后没有声音。 在finder中输出文件的描述大约是14秒。 当我使用VLC时,即使在VLC中的文件浏览器中显示的持续时间为14,它也会正确播放6秒钟并停止播放。我的MPlayer无法正常工作。 我还在Finder中做了预览音频,它可以正确播放6秒钟,然后停止播放。 但是MP3的圆形导杆没有到尽头。 它也说14秒而不是6秒。
我的目标是通过REST API将这6秒的文件流式传输到前端。 我希望用户能够正确下载此文件。 理想情况下,它不会有不一致的元数据(14秒而不是6秒)。
还有什么(本质上)类似于OpenCV的东西,但是用于处理音频并从中获取一些智能? 功能范围包括:-
如果该库可以处理原始音频就可以了。 格式/编码转换是其他现有库(例如ffmpeg的文件)处理的外部问题。
我不是该领域的专家,但是需要使用这样的API,并且想知道是否存在这样的库,因此我选择术语来确定功能可能不是最好的,因此专家可能希望编辑这个问题。