MPMediaItems необработанные данные песни
Мне было интересно, как получить доступ к необработанным данным MPMediaItem.
Есть идеи?
3 ответа
Вы можете получить данные медиа-элемента следующим образом:
-(void)mediaItemToData
{
// Implement in your project the media item picker
MPMediaItem *curItem = musicPlayer.nowPlayingItem;
NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
presetName: AVAssetExportPresetPassthrough];
exporter.outputFileType = @"public.mpeg-4";
NSString *exportFile = [[self myDocumentsDirectory] stringByAppendingPathComponent:
@"exported.mp4"];
NSURL *exportURL = [[NSURL fileURLWithPath:exportFile] retain];
exporter.outputURL = exportURL;
// do the export
// (completion handler block omitted)
[exporter exportAsynchronouslyWithCompletionHandler:
^{
NSData *data = [NSData dataWithContentsOfFile: [[self myDocumentsDirectory]
stringByAppendingPathComponent: @"exported.mp4"]];
// Do with data something
}];
}
Этот код будет работать только на ios 4.0 и выше
Удачи!
Конечно, вы можете получить доступ к данным MPMediaItem
, Это не кристально ясно, но это работает. Вот как:
- Получить URL-адрес элемента мультимедиа
MPMediaItemPropertyAssetURL
имущество - Инициализировать
AVURLAsset
с этим URL - Инициализировать
AVAssetReader
с этим активом - Получить
AVAssetTrack
Вы хотите читать изAVURLAsset
- Создать
AVAssetReaderTrackOutput
с этим треком - Добавьте этот вывод в
AVAssetReader
создан до и-startReading
- Получить все данные с
AVAssetReaderTrackOutput
"s-copyNextSampleBuffer
- PROFIT!
Вот пример кода из моего проекта (это не моя жемчужина кода, я написал его некоторое время назад, в мои темные времена):
typedef enum {
kEDSupportedMediaTypeAAC = 'aac ',
kEDSupportedMediaTypeMP3 = '.mp3'
} EDSupportedMediaType;
- (EDLibraryAssetReaderStatus)prepareAsset {
// Get the AVURLAsset
AVURLAsset *uasset = [m_asset URLAsset];
// Check for DRM protected content
if (uasset.hasProtectedContent) {
return kEDLibraryAssetReader_TrackIsDRMProtected;
}
if ([uasset tracks] == 0) {
DDLogError(@"no asset tracks found");
return AVAssetReaderStatusFailed;
}
// Initialize a reader with a track output
NSError *err = noErr;
m_reader = [[AVAssetReader alloc] initWithAsset:uasset error:&err];
if (!m_reader || err) {
DDLogError(@"could not create asset reader (%i)\n", [err code]);
return AVAssetReaderStatusFailed;
}
// Check tracks for valid format. Currently we only support all MP3 and AAC types, WAV and AIFF is too large to handle
for (AVAssetTrack *track in uasset.tracks) {
NSArray *formats = track.formatDescriptions;
for (int i=0; i<[formats count]; i++) {
CMFormatDescriptionRef format = (CMFormatDescriptionRef)[formats objectAtIndex:i];
// Check the format types
CMMediaType mediaType = CMFormatDescriptionGetMediaType(format);
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(format);
DDLogVerbose(@"mediaType: %s, mediaSubType: %s", COFcc(mediaType), COFcc(mediaSubType));
if (mediaType == kCMMediaType_Audio) {
if (mediaSubType == kEDSupportedMediaTypeAAC ||
mediaSubType == kEDSupportedMediaTypeMP3) {
m_track = [track retain];
m_format = CFRetain(format);
break;
}
}
}
if (m_track != nil && m_format != NULL) {
break;
}
}
if (m_track == nil || m_format == NULL) {
return kEDLibraryAssetReader_UnsupportedFormat;
}
// Create an output for the found track
m_output = [[AVAssetReaderTrackOutput alloc] initWithTrack:m_track outputSettings:nil];
[m_reader addOutput:m_output];
// Start reading
if (![m_reader startReading]) {
DDLogError(@"could not start reading asset");
return kEDLibraryAssetReader_CouldNotStartReading;
}
return 0;
}
- (OSStatus)copyNextSampleBufferRepresentation:(CMSampleBufferRepresentationRef *)repOut {
pthread_mutex_lock(&m_mtx);
OSStatus err = noErr;
AVAssetReaderStatus status = m_reader.status;
if (m_invalid) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_Invalidated;
}
else if (status != AVAssetReaderStatusReading) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_NoMoreSampleBuffers;
}
// Read the next sample buffer
CMSampleBufferRef sbuf = [m_output copyNextSampleBuffer];
if (sbuf == NULL) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_NoMoreSampleBuffers;
}
CMSampleBufferRepresentationRef srep = CMSampleBufferRepresentationCreateWithSampleBuffer(sbuf);
if (srep && repOut != NULL) {
*repOut = srep;
}
else {
DDLogError(@"CMSampleBufferRef corrupted");
EDCFShow(sbuf);
err = kEDLibraryAssetReader_BufferCorrupted;
}
CFRelease(sbuf);
pthread_mutex_unlock(&m_mtx);
return err;
}
Вы не можете, и нет обходного пути. MPMediaItem - это не фактический элемент мультимедиа, это просто метаданные об элементе мультимедиа, переданные приложению через RPC из другого процесса. Данные для самого элемента недоступны в вашем адресном пространстве.
Должен отметить, что даже если у вас есть MPMediaItem, его данные, вероятно, не загружаются в память устройства. Вспышка на iPhone медленная, а памяти мало. Хотя Apple может и не захотеть, чтобы вы имели доступ к необработанным данным, поддерживающим MPMediaItem, вполне вероятно, что они не удосужились заняться этим, поскольку не хотели тратить время, необходимое для работы с API. Если бы они предоставили доступ к такой вещи, то почти наверняка это не NSData, но, скорее всего, NSURL, они бы дали ваше приложение, которое позволило бы ему открыть файл и выполнить потоковую передачу данных.
В любом случае, если вам нужна функциональность, вы должны отправить запрос об ошибке с запросом.
Также, как примечание, не указывайте свой возраст в сообщении об ошибке, которое вы отправляете в Apple. Я думаю, что очень здорово, что вы пишете приложения для телефона, когда я был в вашем возрасте, я любил экспериментировать с компьютерами (тогда я работал над вещами, написанными на Лиспе). Дело в том, что вы не можете юридически согласиться на контракт в Соединенных Штатах, поэтому соглашение о разработке специально запрещает вам присоединяться. Из первого абзаца договора:
Вы также подтверждаете, что достигли совершеннолетия в юрисдикции, в которой проживаете (не менее 18 лет во многих странах), и вы подтверждаете, что по закону вам разрешено стать зарегистрированным разработчиком iPhone.
Если вы упомянете представителю WWDR, что вы не достигли совершеннолетия, они могут осознать, что вы нарушаете соглашение, и обязаны закрыть свою учетную запись разработчика. Просто дружеское предупреждение.