如何在sqlite3数据库中存储音频文件并在iphone中播放?

时间:2022-07-10 13:34:38

i want to store audio files(any of these formats mp3,wav,and iphone supported) in database and play them in iphone...any idea how to do this?

我想在数据库中存储音频文件(任何这些格式mp3,wav和iphone支持)并在iphone中播放...任何想法如何做到这一点?

3 个解决方案

#1


I don't know why you would want to store the audio files in a SQL database but sqlite3 supports BLOB. So store them as BLOB and retrieve them.

我不知道你为什么要将音频文件存储在SQL数据库中,但sqlite3支持BLOB。所以将它们存储为BLOB并检索它们。

Alternatively why not store references to the files that you want to play?

或者,为什么不存储对要播放的文件的引用?

#2


In general it's best to not store binary files in any database. You are better off writing that file to the disk as a file and then storing the path in the database.

通常,最好不要将二进制文件存储在任何数据库中。最好将该文件作为文件写入磁盘,然后将该路径存储在数据库中。

#3


It's not always best to store the file on disk. Have a look at this comparison:

将文件存储在磁盘上并不总是最好的。看看这个比较:

http://www.sqlite.org/intern-v-extern-blob.html

Here is how I do it using ruby and the sequel gem:

以下是我使用ruby和续集gem的方法:

Create a table using this schema. The file is a blob, the sha is the name of the file. In this case, all my files are variable bit rate mono mp3 files, 2K-3K in size. I have about 40 000 files in the db. I'm using a sha1 value as file name since I have a lot of entries that have the same sound so I'm saving some space.

使用此架构创建表。该文件是blob,sha是文件的名称。在这种情况下,我的所有文件都是可变比特率单声道mp3文件,大小为2K-3K。我在db中有大约40 000个文件。我使用sha1值作为文件名,因为我有很多具有相同声音的条目,所以我节省了一些空间。

CREATE TABLE `sound` (`id` integer PRIMARY KEY AUTOINCREMENT, `sha` text, `file` blob); CREATE INDEX `sound_sha_index` ON `sound` (`sha`);

Using ruby you can create the db like this:

使用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

Load the files into the database. Assuming you have the files in a directory called 'sound', here is how:

将文件加载到数据库中。假设您将文件放在名为“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

Play sound in the iPhone app. Copy the sound.db file to your iPhone project. This is the code I'm using. It's based on FMDB and AVAudioPlayer.

在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

Use the file from somewhere in your code like this:

使用代码中某处的文件,如下所示:

self.soundPlayer = [[SoundPlayer alloc] init];
[self.soundPlayer play:[entry valueForKey:@"sha"]];

where [entry valueForKey:@"sha"]] returns a NSString which is the file name I have stored in my other table of entries.

其中[entry valueForKey:@“sha”]]返回一个NSString,它是我在其他条目表中存储的文件名。

#1


I don't know why you would want to store the audio files in a SQL database but sqlite3 supports BLOB. So store them as BLOB and retrieve them.

我不知道你为什么要将音频文件存储在SQL数据库中,但sqlite3支持BLOB。所以将它们存储为BLOB并检索它们。

Alternatively why not store references to the files that you want to play?

或者,为什么不存储对要播放的文件的引用?

#2


In general it's best to not store binary files in any database. You are better off writing that file to the disk as a file and then storing the path in the database.

通常,最好不要将二进制文件存储在任何数据库中。最好将该文件作为文件写入磁盘,然后将该路径存储在数据库中。

#3


It's not always best to store the file on disk. Have a look at this comparison:

将文件存储在磁盘上并不总是最好的。看看这个比较:

http://www.sqlite.org/intern-v-extern-blob.html

Here is how I do it using ruby and the sequel gem:

以下是我使用ruby和续集gem的方法:

Create a table using this schema. The file is a blob, the sha is the name of the file. In this case, all my files are variable bit rate mono mp3 files, 2K-3K in size. I have about 40 000 files in the db. I'm using a sha1 value as file name since I have a lot of entries that have the same sound so I'm saving some space.

使用此架构创建表。该文件是blob,sha是文件的名称。在这种情况下,我的所有文件都是可变比特率单声道mp3文件,大小为2K-3K。我在db中有大约40 000个文件。我使用sha1值作为文件名,因为我有很多具有相同声音的条目,所以我节省了一些空间。

CREATE TABLE `sound` (`id` integer PRIMARY KEY AUTOINCREMENT, `sha` text, `file` blob); CREATE INDEX `sound_sha_index` ON `sound` (`sha`);

Using ruby you can create the db like this:

使用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

Load the files into the database. Assuming you have the files in a directory called 'sound', here is how:

将文件加载到数据库中。假设您将文件放在名为“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

Play sound in the iPhone app. Copy the sound.db file to your iPhone project. This is the code I'm using. It's based on FMDB and AVAudioPlayer.

在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

Use the file from somewhere in your code like this:

使用代码中某处的文件,如下所示:

self.soundPlayer = [[SoundPlayer alloc] init];
[self.soundPlayer play:[entry valueForKey:@"sha"]];

where [entry valueForKey:@"sha"]] returns a NSString which is the file name I have stored in my other table of entries.

其中[entry valueForKey:@“sha”]]返回一个NSString,它是我在其他条目表中存储的文件名。