web-dev-qa-db-ja.com

iOSでオーディオファイルの長さを取得する方法は?

NSDictionary* fileAttributes = 
    [[NSFileManager defaultManager] attributesOfItemAtPath:filename 
                                                     error:nil]

ファイル属性キーから、日付、サイズなどを取得できます。しかし、どのように期間を取得しますか?

44
Namratha

NSFileManagerクラス参照の 'File Attribute Keys'にNSFileManagerインスタンスがファイルについて取得するすべての情報は、オペレーティングシステム内の実際のファイル自体のプロパティと関係しています。 NSFileManagerは実際にはファイルを解釈しません。

ファイルの継続時間を取得するには、ファイルの解釈方法を知っているクラスを使用する必要があります。 AVFoundationフレームワークは、必要な正確なクラスAVAssetを提供します。具体的なサブクラスAVURLAssetを使用してこの抽象クラスのインスタンスをインスタンス化し、[〜# 〜] nsurl [〜#〜]期間を取得したいオーディオファイルを指します。その後、durationプロパティをクエリすることにより、AVAssetインスタンスから期間を取得できます。

例えば:

AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:audioFileURL options:nil];
CMTime audioDuration = audioAsset.duration;
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);

AVFoundationは、パフォーマンスとユーザーエクスペリエンス全体を改善するために、非常に非同期なフレームワークとして設計されていることに注意してください。メディアファイルの継続時間のクエリなどの単純なタスクを実行する場合でも、長時間かかる可能性があり、アプリケーションがハングする可能性があります。 AVAsynchronousKeyValueLoading protocol を使用して、曲の継続時間を非同期にロードし、完了ハンドラーブロックでUIを更新する必要があります。 'Block Programming Guide' および「Discovering AV Foundation」というタイトルのWWDC2010ビデオは、 https://developer.Apple.com/videos/wwdc/2010 から無料で入手できます。

126
James Bedford

完全性のために-mp3ファイルの継続時間を取得する別の方法があります。

NSURL * pathToMp3File = ...
NSError *error = nil;
AVAudioPlayer* avAudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pathToMp3File error:&error];

double duration = avAudioPlayer.duration; 
avAudioPlayer = nil;

私はこれを識別可能な遅延なしで使用しました。

14
John Goodstadt

Swiftを使用して同じことを実現できます。

let audioAsset = AVURLAsset.init(url: audioFileURL, options: nil)
let duration = audioAsset.duration
let durationInSeconds = CMTimeGetSeconds(duration)
8
Ashildr

まだこれを探している人のために。答えに基づいて、Swift 4のコード(Appleのドキュメントから取得した値の非同期読み込みを含む):

let audioAsset = AVURLAsset.init(url: yourURL, options: nil)

audioAsset.loadValuesAsynchronously(forKeys: ["duration"]) {
    var error: NSError? = nil
    let status = audioAsset.statusOfValue(forKey: "duration", error: &error)
    switch status {
    case .loaded: // Sucessfully loaded. Continue processing.
        let duration = audioAsset.duration
        let durationInSeconds = CMTimeGetSeconds(duration)
        print(Int(durationInSeconds))
        break              
    case .failed: break // Handle error
    case .cancelled: break // Terminate processing
    default: break // Handle all other cases
    }
}
6
nCr78

Swift 5.0 + iOS 12:これが私にとって唯一の方法です(Swiftの@John Goodstadtソリューション)。現在、理由はわかりませんが、録音されたオーディオファイル(私の場合はボイスメモ)と次のコードを使用して受信したオーディオファイルとの間に平均0.2秒の差があります。

    do {
        let audioPlayer = try AVAudioPlayer(contentsOf: fileURL)
        return CGFloat(audioPlayer.duration)
    } catch {
        assertionFailure("Failed crating audio player: \(error).")
        return nil
    }
1
Baran