【发布时间】:2010-11-06 14:03:16
【问题描述】:
我想在数据库中存储音频文件(任何这些格式的 mp3、wav 和 iphone 支持) 并在 iphone 中播放它们...知道怎么做吗?
【问题讨论】:
-
将文件存储在磁盘上并不总是最好的。看看这个比较:sqlite.org/intern-v-extern-blob.html
标签: objective-c iphone xcode audio sqlite
我想在数据库中存储音频文件(任何这些格式的 mp3、wav 和 iphone 支持) 并在 iphone 中播放它们...知道怎么做吗?
【问题讨论】:
标签: objective-c iphone xcode audio sqlite
我不知道您为什么要将音频文件存储在 SQL 数据库中,但 sqlite3 支持 BLOB。所以将它们存储为 BLOB 并检索它们。
另外,为什么不存储对您要播放的文件的引用?
【讨论】:
https://www.sqlite.org/fasterthanfs.html
一般来说,最好不要将二进制文件存储在任何数据库中。您最好将该文件作为文件写入磁盘,然后将路径存储在数据库中。
【讨论】:
将文件存储在磁盘上并不总是最好的。看看这个比较:
http://www.sqlite.org/intern-v-extern-blob.html
这是我使用 ruby 和续集 gem 的方法:
使用此架构创建表。该文件是一个 blob,sha 是文件的名称。在这种情况下,我所有的文件都是可变比特率的单声道 mp3 文件,大小为 2K-3K。我在数据库中有大约 40 000 个文件。我使用 sha1 值作为文件名,因为我有很多具有相同声音的条目,所以我节省了一些空间。
CREATE TABLE `sound` (`id` integer PRIMARY KEY AUTOINCREMENT, `sha` text, `file` blob); CREATE INDEX `sound_sha_index` ON `sound` (`sha`);
使用 ruby,您可以像这样创建数据库:
db = Sequel.sqlite('./sound.db')
db.create_table :sound do
primary_key :id, :index => true
column :sha, :text, :index => true
column :file, :blob
end
将文件加载到数据库中。假设您将文件放在名为“sound”的目录中,方法如下:
DB = Sequel.sqlite('./sound.db')
files = Dir['./sound/*.mp3']
files.each_with_index do |f, i|
# progress
print "\r #{((i.to_f / files.size)*100).round(2)}%"
# get the file name without directory and extension
f =~ /\/sound\/(.+)\.mp3/
# insert into db
DB[:sound].insert :sha => $1, :file => File.read("#{f}").to_sequel_blob
end
在 iPhone 应用中播放声音。将 sound.db 文件复制到您的 iPhone 项目中。这是我正在使用的代码。它基于 FMDB 和 AVAudioPlayer。
SoundPlayer.h
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import "FMDatabase.h"
#import "FMDatabaseQueue.h"
@interface SoundPlayer : NSObject
{
FMDatabaseQueue *db;
}
@property (nonatomic, retain) AVAudioPlayer *audioPlayer;
- (void)play:(NSString *)sha;
- (void)free;
@end
SoundPlayer.m
#import "SoundPlayer.h"
#import "DictAppDelegate.h"
@implementation SoundPlayer
- (SoundPlayer*)init
{
NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"sound.db"];
db = [FMDatabaseQueue databaseQueueWithPath: dbPath];
return self;
}
- (void)play:(NSString *)sha
{
[db inDatabase:^(FMDatabase *connection) {
// Execute and fetch result
NSString *query = [NSString stringWithFormat:@"select file from sound where sha = '%@' limit 1", sha];
FMResultSet *rs = [connection executeQuery:query];
while([rs next]) {
NSData *file = [rs dataForColumn: @"file"];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithData: file error:&error];
self.audioPlayer.numberOfLoops = 0;
self.audioPlayer.volume = 1.0f;
[self.audioPlayer prepareToPlay];
if (self.audioPlayer == nil) {
NSLog(@"Error playing sound: %@", [error description]);
} else {
[self.audioPlayer play];
}
}
}];
}
// Cleanup
- (void)free {
[db close];
}
@end
在代码中的某处使用该文件,如下所示:
self.soundPlayer = [[SoundPlayer alloc] init];
[self.soundPlayer play:[entry valueForKey:@"sha"]];
其中 [entry valueForKey:@"sha"]] 返回一个 NSString,它是我存储在其他条目表中的文件名。
【讨论】:
db = Sequel.sqlite('./sound.db') db.create_table :sound do primary_key :id, :index => true column :sha, :text, :index => true column :file, :blob end