IOS開(kāi)發(fā):iPod的音樂(lè)庫(kù)中的音頻如何上傳到服務(wù)器中

最近在做的項(xiàng)目里有一個(gè)功能,就是拿到手機(jī)媒體庫(kù)中的音頻文件伦籍,并實(shí)現(xiàn)APP中的播放蓝晒,已經(jīng)轉(zhuǎn)成MP3格式上傳到服務(wù)器上。

首先是要能獲取到ipod library中的音頻帖鸦。這里我用的是MPMediaQuery芝薇,在這里有一個(gè)坑,可以拿到的歌曲中有很多歌曲的AssetURL為nil作儿,這是因?yàn)镸PMediaQuery只能拿到用戶通過(guò)itunes倒入進(jìn)去的歌曲url洛二。
代碼如下:

   // 1.創(chuàng)建媒體選擇隊(duì)列(從ipod庫(kù)中讀出音樂(lè)文件) 
MPMediaQuery*everything = [[MPMediaQueryalloc]init];
 // 2.創(chuàng)建讀取條件(類似于對(duì)數(shù)據(jù)做一個(gè)篩選)  Value:作用等同于MPMediaType枚值
MPMediaPropertyPredicate*albumNamePredicate =
[MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInt:MPMediaTypeMusic ] forProperty: MPMediaItemPropertyMediaType];
//3.給隊(duì)列添加讀取條件
  [everythingaddFilterPredicate:albumNamePredicate];
 //4.從隊(duì)列中獲取符合條件的數(shù)組集合
   NSArray*itemsFromGenericQuery = [everythingitems];
  //5.便利解析數(shù)據(jù)
 for(MPMediaItem*songinitemsFromGenericQuery) {
  //歌曲名字
   > NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
    //歌曲路徑
    NSString *url = [song valueForProperty: MPMediaItemPropertyAssetURL];
    //歌手
     NSString *songer = [song valueForProperty: MPMediaItemPropertyArtist];
  }

拿到后肯定是實(shí)現(xiàn)APP中的播放,這個(gè)就很簡(jiǎn)單了攻锰。采用AVAudioPlayer就好了

接著就是重點(diǎn)了晾嘶。項(xiàng)目需要把該音頻上傳到服務(wù)器,但是拿到的AssetURL并不支持后臺(tái)上傳娶吞,它是這樣的:pod-library://item/item.m4a?id=8461911140233300129***

經(jīng)過(guò)一番查閱垒迂,最終找到一個(gè)辦法,就是先把它轉(zhuǎn)為caf 寫(xiě)到內(nèi)存里妒蛇,然后再把.caf轉(zhuǎn)為.mp3 就可以上傳了机断。這里caf轉(zhuǎn)mp3需要使用第三方庫(kù):lame (lame三庫(kù)的資源

代碼如下:
1.導(dǎo)出成caf格式,這種導(dǎo)出方式绣夺,文件名必須以.caf作為后綴

- (void)convertToCAF:(NSString *)songUrl name:(NSString *)songName
{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [UsingHUD showInView:self.view text:@"正在處理毫缆,請(qǐng)稍等..."];
});
NSURL *url = [NSURL URLWithString:songUrl];
//由于中文歌名不行 這邊采用時(shí)間戳
NSString *fileName      = [NSString stringWithFormat:@"%@.caf",[self getTimestamp]];

AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil];

NSError *assetError = nil;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset
                                                            error:&assetError];
if (assetError) {
    NSLog (@"error: %@", assetError);
    return;
}

AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
                                           assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
                                           audioSettings: nil];
if (! [assetReader canAddOutput: assetReaderOutput]) {
    NSLog (@"can't add reader output... die!");
    return;
}
[assetReader addOutput: assetReaderOutput];

NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
NSString *exportPath = [documentsDirectoryPath stringByAppendingPathComponent:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL
                                                       fileType:AVFileTypeCoreAudioFormat
                                                          error:&assetError];
if (assetError) {
    NSLog (@"error: %@", assetError);
    return;
}
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
                                [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
                                nil];
AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
                                                                           outputSettings:outputSettings];
if ([assetWriter canAddInput:assetWriterInput]) {
    [assetWriter addInput:assetWriterInput];
} else {
    NSLog (@"can't add asset writer input... die!");
    return;
}

assetWriterInput.expectsMediaDataInRealTime = NO;

[assetWriter startWriting];
[assetReader startReading];

AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
[assetWriter startSessionAtSourceTime: startTime];

__block UInt64 convertedByteCount = 0;

dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
[assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue
                                        usingBlock: ^
 {
     // NSLog (@"top of block");
     while (assetWriterInput.readyForMoreMediaData) {
         CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
         if (nextBuffer) {
             // append buffer
             [assetWriterInput appendSampleBuffer: nextBuffer];
             //             NSLog (@"appended a buffer (%d bytes)",
             //                    CMSampleBufferGetTotalSampleSize (nextBuffer));
             convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
             
             
         } else {
             // done!
             [assetWriterInput markAsFinished];
             [assetWriter finishWriting];
             [assetReader cancelReading];
             NSDictionary *outputFileAttributes = [[NSFileManager defaultManager]
                                                   attributesOfItemAtPath:exportPath
                                                   error:nil];
             //實(shí)現(xiàn)caf 轉(zhuǎn)mp3
             [self audioCAFtoMP3:exportPath];
      
             NSLog (@"done. file size is %lld",
                    [outputFileAttributes fileSize]);
             break;
         }
     }
     
 }];
}

2.caf >mp3

- (void)audioCAFtoMP3:(NSString *)wavPath {

NSString *cafFilePath = wavPath;

NSString *mp3FilePath = [NSString stringWithFormat:@"%@.mp3",[NSString stringWithFormat:@"%@",[cafFilePath substringToIndex:cafFilePath.length - 4]]];

@try {
    int read, write;
    
    FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");  //source 被轉(zhuǎn)換的音頻文件位置
    fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
    FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb");  //output 輸出生成的Mp3文件位置
    
    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;
    short int pcm_buffer[PCM_SIZE*2];
    unsigned char mp3_buffer[MP3_SIZE];
    
    lame_t lame = lame_init();
    lame_set_num_channels(lame,1);//設(shè)置1為單通道,默認(rèn)為2雙通道
    lame_set_in_samplerate(lame, 44100.0);
    lame_set_VBR(lame, vbr_default);
    
    lame_set_brate(lame,8);
    
    lame_set_mode(lame,3);
    
    lame_set_quality(lame,2);
    
    lame_init_params(lame);
    
    do {
        read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
        if (read == 0)
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
        else
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
        
        fwrite(mp3_buffer, write, 1, mp3);
        
    } while (read != 0);
    
    lame_close(lame);
    fclose(mp3);
    fclose(pcm);
}
@catch (NSException *exception) {
    NSLog(@"%@",[exception description]);
}
@finally {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [UsingHUD hideInView:self.view];
        //主線程上傳到oss
        [self localdispose:mp3FilePath];
    });

}
}

到此乐导,大功告成~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末苦丁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子物臂,更是在濱河造成了極大的恐慌旺拉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棵磷,死亡現(xiàn)場(chǎng)離奇詭異蛾狗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仪媒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門沉桌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谢鹊,“玉大人,你說(shuō)我怎么就攤上這事留凭〉瓒螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蔼夜,是天一觀的道長(zhǎng)兼耀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)求冷,這世上最難降的妖魔是什么瘤运? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮匠题,結(jié)果婚禮上拯坟,老公的妹妹穿的比我還像新娘。我一直安慰自己韭山,他們只是感情好似谁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掠哥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秃诵。 梳的紋絲不亂的頭發(fā)上续搀,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音菠净,去河邊找鬼禁舷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛毅往,可吹牛的內(nèi)容都是我干的牵咙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼攀唯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洁桌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起侯嘀,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤另凌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后戒幔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吠谢,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年诗茎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了工坊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖王污,靈堂內(nèi)的尸體忽然破棺而出罢吃,到底是詐尸還是另有隱情,我是刑警寧澤玉掸,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布刃麸,位于F島的核電站,受9級(jí)特大地震影響司浪,放射性物質(zhì)發(fā)生泄漏泊业。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一啊易、第九天 我趴在偏房一處隱蔽的房頂上張望吁伺。 院中可真熱鬧,春花似錦租谈、人聲如沸篮奄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)各薇。三九已至,卻和暖如春涧窒,著一層夾襖步出監(jiān)牢的瞬間空入,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工咖城, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茬腿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓宜雀,卻偏偏與公主長(zhǎng)得像切平,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辐董,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容