Welcome to the Geeks & God Static Archive. Read more »

Drupal: Converting From Audio Module To Filefield Module

User Rating:
4.12245
Average: 4.1 (49 votes)

This tutorial covers migrating from the audio module to using CCK and filefield to store your audio files in drupal 6.

Edit: Before updating be sure to create a backup of your database and files. If something could go wrong it probably will.

Why Switch?

The Audio module has served well as an audio solution for many years. As drupal has become more flexible there are now a number of ways to manage audio files in drupal. On top of that, the 'drupal way' has changed from being unique content types for audio to unique fields on nodes to handle audio.

Moving From Drupal 5

If you are moving from drupal 5 first upgrade both drupal and the audio module to drupal 6. At the time this tutorial is being written there isn't a formal release of the audio module for drupal 6. In that case use the development version. Be sure to run update.php.

Create Your New Node Type

Create a new content type for your audio nodes to become. The audio module owns the audio node type and we need a node type that is separated from the audio module. For example, if you run a podcast you can create a node type called podcast.

Then, using CCK and Filefield add a new field to your new node type that will hold the audio. For example, if the file is going to be an mp3 file for your podcast you might call the file MP3 File with a machine name field_mp3_file.

Setting Up Your Migration Script

For a more in depth look at the setup and a general migration process read "Migrating the Drupal way. Part I: creating a node."
Instead of writing a module we are going to do the migration with a migration script. Create a new file in you root drupal directory with a name like migrate.php. This is the same directory your index.php file is in.

This file should start with:

<?php
// Bootstrap Drupal
require 'includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

This will load your drupal installation and give you full access to drupal.

Converting A Single Node

To convert a single node from one type to another is fairly straight forward. You load the node, change the node type, convert the audio file to a filefield file, and save the changes. Let's walk through a code example.

In this first step we load the node and change its type. Replace 123 with the node id you want to convert and the type with the machine name of the new type you created.

$node = node_load(123);
 
// Change the node type
$node->type = 'podcast';

In this next step me migrate the file information from the audio module to the filefield module. Replace field_mp3_file with the machine name of the field you created previously. This moves the information from one place to another. The fid referred to in this section is the file id recorded in drupals file management system. The unset command removes the audio modules information from the node.

// Migrate the audio file to filefield
$node->field_mp3_file[] = array(
	'fid' => $node->audio['file']->fid,
	'list' => 1, // Set to 1 to display on the node or 0 to hide.
	'uid' => $node->audio['file']->uid,
	'filename' => $node->audio['file']->filename,
	'filepath' => $node->audio['file']->filepath,
	'filemime' => $node->audio['file']->filemime,
	'filesize' => $node->audio['file']->filesize,
	'status' => $node->audio['file']->status,
	'timestamp' => $node->audio['file']->timestamp,
);
unset($node->audio);

In the final step we save the changes. Calling node_save makes sure all the proper hooks are called and the node is updated.

node_save($node);

Converting Multiple Nodes

Converting multiple nodes is just one additional step. We enclose the script above in a wrapper that loads the nodes we want to convert.

For example, a script that converts all audio module nodes to podcast nodes would look like:

<?php
// Bootstrap Drupal
require 'includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
// Query all the audio nodes.
$result = db_query("SELECT nid FROM {node} WHERE type = 'audio'");
 
// Loop through all the audio nodes.
while ($nid = db_fetch_object($result)) {
  // Load the node.
  $node = node_load($nid->nid);
 
  // Change the node type
  $node->type = 'podcast';
 
  // Migrate the audio file to filefield
  $node->field_mp3_file[] = array(
	'fid' => $node->audio['file']->fid,
	'list' => 1, // Set to 1 to display on the node or 0 to hide.
	'uid' => $node->audio['file']->uid,
	'filename' => $node->audio['file']->filename,
	'filepath' => $node->audio['file']->filepath,
	'filemime' => $node->audio['file']->filemime,
	'filesize' => $node->audio['file']->filesize,
	'status' => $node->audio['file']->status,
	'timestamp' => $node->audio['file']->timestamp,
  );
  // Remove the audio module informaion.
  unset($node->audio);
 
  // Save the changes
  node_save($node);
}

Run the script and clean up

When you're all setup, you can just visit the script's file URL in your browser or even run it from the command line. That will execute the script. When you are done migrating be sure to remove the migration script from your drupal root directory.

The Bomb

5

Oh yeah. Nice work MF. Even I could probably do this (in a pinch :) ) This is powerful stuff and has huge implications for converting any type of content.

Love this tutorial.

-Rob Feature
Geeks and God Co-Host
www.mustardseedmedia.com

Potentially Complicated, Made Simple!

5

Thank you for making the potentially complicated simple. I see how I could maybe use this approach to move from Node Profile to just Drupal's core profile capabilities also.

Timeout

5

I also appreciate this tutorial. Last week I wrote a similar function, but it wasn't this elegant.

Depending on how many nodes there are to process and the php.ini settings I believe this could timeout before completion. There is probably an easy line of code that could be added to prevent timeout, but I just changed the max_execution_time and max_input_time values in php.ini. What is the recommended way to handle this?

set_time_limit

There are a number of ways to set or change the time limit in php. In this case I would usually use set_time_limit(). Calling this function will reset the time limit. If I was 20 seconds into a scripts execution and called set_time_limit(30) the script would run for 50 seconds in total.

I would typically place this right after initializing drupal.

Make sense?

Matt Farina
Geeks and God Former Co-Host
www.mattfarina.com

Elegant, thanks for sharing!

5

A very nice way to use drupal to migrate itself, no need to worry about much, since drupal does it very well.

I listened to the podcast where you discussed this, and left me wondering about it, many thanks for writing this tutorial!

So..

4

So, how would one go about doing this in the following scenario:

A current 5.x install w/ audio module to a different 6.x install w/ ff/cck? Or would it be "easier" to just recreate all the nodes using ff/cck/ffpc in the 6.x install?

by the way: the rating field should not be a required field.

Uh oh....

4

Hey MF,

Okey dokey, so I like the tutorial. I really like the simplicity of ff over the audio module and though I understand your php snippet above about as well as ancient greek, I can see what you have designed. I went ahead and set up a smaller version of my site on a local host and ran the migration script and it looks like it worked. I see now the need for css, but there is also this nasty red/pink box filled with errors that I don't know how to interpret. Any ideas?

* warning: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object in C:\wamp\www\olivebranchonline\sites\all\modules\date\date\date_elements.inc on line 48.
* warning: Invalid argument supplied for foreach() in C:\wamp\www\olivebranchonline\sites\all\modules\filefield\filefield_field.inc on line 127.
* warning: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object in C:\wamp\www\olivebranchonline\sites\all\modules\date\date\date_elements.inc on line 48.
* warning: Invalid argument supplied for foreach() in C:\wamp\www\olivebranchonline\sites\all\modules\filefield\filefield_field.inc on line 127.
* warning: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object in C:\wamp\www\olivebranchonline\sites\all\modules\date\date\date_elements.inc on line 48.
* warning: Invalid argument supplied for foreach() in C:\wamp\www\olivebranchonline\sites\all\modules\filefield\filefield_field.inc on line 127.

Thanks again.
Shalom, pk

Need your script

I would need to see your script to know what's causing the problem. If you're having issues start a forum topic and it can be worked through.

Matt Farina
Geeks and God Former Co-Host
www.mattfarina.com

Off to the forum.

Thanks for the comment. I am off to the forum.

Very useful tutorial

5

Hey Matt,

I just realized I never posted a comment on this tutorial. It's awesome, man! I used it to convert my audio nodes to cck, and also as a template for converting a bunch of other stuff. (For example, I migrated book nodes to page nodes, and also converted some node bodies so I could get rid of an unwanted input filter.)

Anyway, I pulled some additional info from audio tags and audio data into some additional CCK fields for Artist, Composer, Copyright and Duration.

  if ($node->audio_tags['artist']){ $node->field_audio_artist[0]['value'] = $node->audio_tags['artist']; }
  if ($node->audio_tags['composer']){ $node->field_audio_composer[0]['value'] = $node->audio_tags['composer']; }
  if ($node->audio_tags['copyright']){ $node->field_audio_copyright[0]['value'] = $node->audio_tags['copyright']; }
  $node->field_audio_duration[0]['value'] = $node->audio['playtime'];

(The duration can be read directly from the mp3 file using getID3 module, but that's slower, so I chose to store it.)

I also added three lines to do some additional cleanup before the node_save when I ran this:

  unset($node->audio_tags);
  unset($node->url_play);
  unset($node->url_download);

Thanks folks, really great

4

Thanks folks, really great tutorial.
Mike - the drivercure consultant.

When I try running this

3

When I try running this script, I get "Parse error: syntax error, unexpected T_VARIABLE" at the first reference to a member of $node ... do you not? Any idea how to fix this?

Re: Unexpected T_VARIABLE

Tom,

How are you running this. First, did you create this as its own .php file in the webroot, or did you try pasting this as php filter content into a Drupal node? The way Matt wrote this, it's intended to run standalone, the same way that files like cron.php and update.php do.

Second, are you running this from a browser or running php from a shell prompt? If running from a shell prompt, there are some $_SERVER variables that need to get set to keep Drupal from freaking out.

I run all of my scripts from the Linux shell, so I've been adding snippets like this to the top of all my import and conversion scripts lately:

// prevent this from running under apache:
if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
  echo 'nope.  not executing except from the command line.';
  exit(1);
}
 
// set some server variables so Drupal doesn't freak out
$_SERVER['SCRIPT_NAME'] = '/this_file_name.php';
$_SERVER['SCRIPT_FILENAME'] = '/this_file_name.php';
$_SERVER['HTTP_HOST'] = 'www.example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_METHOD'] = 'POST';

Check your web server logs for additional info, as well.

If you're still having trouble with this, can you provide some more details?

Micah

thanks for the coverting guide.

4

I was looking to convert audio module to filefield and found this blog information which helped me nice. Thanks and Regards
BABA

Re: Unexpected T_VARIABLE

3

Hi Micah,

Yes, I'm running this as a standalone PHP file through the browser, with the following contents:

<?php
// Bootstrap Drupal
require 'includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);


$node = node_load(48019);
 
 
// Change the node type
 
$node->type = 'od_audio';
 
 
// Migrate the audio file to filefield
 
$node->field_mp3_file[] = array(
   
'fid' => $node->audio['file']->fid,
   
'list' => 1, // Set to 1 to display on the node or 0 to hide.
   
'uid' => $node->audio['file']->uid,
   
'filename' => $node->audio['file']->filename,
   
'filepath' => $node->audio['file']->filepath,
   
'filemime' => $node->audio['file']->filemime,
   
'filesize' => $node->audio['file']->filesize,
   
'status' => $node->audio['file']->status,
   
'timestamp' => $node->audio['file']->timestamp,
  );
 
// Remove the audio module informaion.
 
unset($node->audio);
 
 
// Save the changes
 
node_save($node); */
}
?>

My PHP error log only gives me the same: "[12-Sep-2009 10:23:48] PHP Parse error: syntax error, unexpected T_VARIABLE in /Users/tog/Sites/import/audio-to-cck.php on line 10"

Any help would be great!

I'm no PHP expert, but it

I'm no PHP expert, but it appears to me that the "*/" and "}" following the "node_save($node);" are unmatched and should be removed.

Hope this helps,
Curt

Re: I'm no PHP expert, but it

4

That's true, but not the problem - it persists without it.

Cannot duplicate your error

5

Tom,

I just tried running the first part of your script both from the command line and the browser and cannot duplicate your error. Here's what I ran:

  1. <?php
  2. // Bootstrap Drupal
  3. require 'includes/bootstrap.inc';
  4. drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
  5.  
  6.  
  7. $node = node_load(315);
  8.  
  9. // Change the node type
  10. $node->type = 'audionew';
  11. ?>

(Changed the nid and content type to match my data, of course.) Line 10 is where you set $node->type and it didn't balk for me. You're running this under Drupal 6 in the root of your Drupal installation, right?

Edit: I even changed this to load a non-existent nid, and it still didn't generate the error. Weird.

Re: Cannot duplicate your error

OK strange, I have it working now! I copied your script (with my variations), and it worked. I then started adding the remaining lines, and it gave me the error once I added node_save. But then I retyped that, and now it's working. Maybe I had some strange characters in there or something...

Thanks anyway

now to convert embedded video

5

This was a great tutorial and although I don't understand all the script it worked just fine.

Now I would like to do the same with the video module http://drupal.org/project/video and switch to http://drupal.org/project/emfield I created a new content type of video_url with a field_video_url but I am not sure about the process that would create a new node id. I want to keep the old node out there until I am sure the new one is OK.

Conversion script for video to embedded video field

5

Well it isn't elegant (my first php program) but it worked!
Here is what I used to convert from the video module to emfield

<?php
// Bootstrap Drupal
require 'includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
require
'modules/node/node.pages.inc';

 
// Construct the new node object once for all
 
$node = new stdClass();
 
$node->type = 'video_url';
$node->status = 1;
$node->promote = 1;
$node->sticky = 0;
$node->format = 1;       // Filtered HTML
$node->uid = 1;          // UID of content owner
$node->language = 'en';
node_object_prepare($node); // just filled in default values for uid, status, promote, status, date, created, and revision properties

// Query all the nodes.
$result = db_query("SELECT nid FROM {node} WHERE type = 'video'");

// Loop through all the nodes.
while ($nid = db_fetch_object($result)) {
 
// Load the node.
 
$old_node = node_load($nid->nid);

 
// Migrate the video-url-field to emfield
$node->title = $old_node->title;
$node->body = $old_node->body;
$node->field_video_url[0]['embed'] = $old_node->vidfile;

print
$node->title/* so we can see what is happening */
print $node->field_video_url.'    ';

$node->created = time();
$node->changed = $node->created;

$node->taxonomy = $old_node->taxonomy;

// creates a new node
$node->nid='';

 
// Save the changes
 
node_save($node);
}
?>

The clean up then is to delete the old video nodes using /admin/content/node which also has a nice function to "reload embedded media data" which I ran on my new nodes (just in case).
A few of my video nodes were files which I decided to handle by manual editing, since I am already over my php ability.

Better conversion of video to emfield

4

Here is a simpler script for converting video to emfield. Maybe someone else will improve on this. http://drupal.org/node/652118

Same situation...

I have the old site on 5.x with audio...about 150 nodes. I now have the new site up and running and about 5 new nodes established. The new site is a 6.x install on a new server and provider. Trying to figure out the best strategy to migrate the 5.x audio over to 6.x.

Maybe some sort of import script? not sure how to shape that.

Migrating Audio Data to a new site

Steve,

The scripts in this tutorial are basically assuming that you've upgraded [a copy of] your existing D5 site to D6 and are now trying to convert the audio data. Are you saying you want to migrate the audio data from the existing site to a new site? That would be a bit different.

I did something like that recently, but it wasn't coming from a Drupal site. I was importing content from an existing non-Drupal podcast.

Basically I used the following process to retrieve the podcast:

$feedurl = "http://example.com/podcast.rss"
$response = drupal_http_request($feedurl);
if ($response->code == '200' ) {
  $xml = simplexml_load_string($response->data);
}
 
$items = $xml->channel->item;
foreach ($items as $item) {
  $title = trim($item->title);
  $pubDate = trim($item->pubDate);
  /*
   * Do the heavy lifting and file retrieval magic here,
   * then create the node and save it.
   */
}

Unfortunately, the full details of how I did this would be its own tutorial, and methods would vary from site to site. This probably wouldn't retrieve most of the audio fields from the old site, because they wouldn't necessarily be in the podcast feed. It worked in my case because everything I wanted to import into Drupal was in the idv3 tags inside the mp3 files, and I used functions from the getid3 module to extract them. (Granted, the audio module lets you write custom tags into your mp3 files, so your field data might be there.)

hey man, i know its 2 years

hey man, i know its 2 years down the line, but im trying to implement this method u mention to pull the id3 tags and save them as cck fields but im not having any luck, could u help me out maybe?

much appreciated

this is the code im using

<?php
// This is for a single node

// Bootstrap Drupal
require 'includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
require
'modules/node/node.pages.inc';

$node = node_load(111);

// Change the node type
$node->type = 'music';

// Migrate the audio file to filefield
$node->field_mp3_audio[] = array(
   
'fid' => $node->audio['file']->fid,
   
'list' => 1, // Set to 1 to display on the node or 0 to hide.
   
'uid' => $node->audio['file']->uid,
   
'filename' => $node->audio['file']->filename,
   
'filepath' => $node->audio['file']->filepath,
   
'filemime' => $node->audio['file']->filemime,
   
'filesize' => $node->audio['file']->filesize,
   
'status' => $node->audio['file']->status,
   
'timestamp' => $node->audio['file']->timestamp,
);

if (
$node->audio_tags['artist']){ $node->field_artist_taxonomy[0]['value'] = $node->audio_tags['artist']; }
 
  unset(
$node->audio);
  unset(
$node->audio_tags);
  unset(
$node->url_play);
  unset(
$node->url_download);
 
node_save($node);
?>

Try setting CCK field arrays differently

I think the problem might just be the way you're coding the array for the CCK field. Try this instead:

if ($node->audio_tags['artist']){
 $node->field_artist_taxonomy[] = array('value' => $node->audio_tags['artist']);
}

a very good tutorial!

3

a very good tutorial!

thanks for this tip as well

thanks for this tip as well

re:jststeve

steve - yes your going to need to update everything 5.x then upgrade the site to 6.x along with all of the 6.x updates you need. from there you can follow the tutorial for converting. I just went through this process myself. I was stuck on a 5.x site for awhile now stumpped by the audio module. I finally bit the bullet and accepted that the audio module was dead and it was time to move on. Now I'm updated to drupal 6. I've test converted a few thousand audio nodes using this method successfully :D.

Onto the production site then upgrading to drupal 7 with no looking behind. good luck in your project.

i think with a few more steps

3

i think with a few more steps you can port from the audio module to the audiofield module:

http://drupal.org/project/audiofield

Migration Questions - Download Count

5

I realize that I'm really late to the party on this one, but I've got a couple questions. I'm using the Audio module on my personal Drupal 6 install for a sermon index library. Obviously I'm looking for other options so that I can eventually get to Drupal 7, but have questions about migrating to either the File_Field or Audio_Field CCK method.

Mainly migration fear, but I have quite a few mp3 files that are indexed on my site (joannamay.org/teaching) and the Audio module supports things like "download count" and with some files at 22,000+ downloads, that's valuable information to my users that I don't want to lose. Is there any way to migrate that data as well, and will things like "download counts" be available in the CCK method?

I'd also like to use an inline audio player that's a little more mobile/tablet-friendly than the flash players used in Audio, but haven't seen a lot of options on that front. Thanks for any insight.

Play count - Download Count

5

we're in the same boat as Jburn.
Upgrading 5.x multi podcast site to a 6.x version with cck/filefield and swftools
but a key piece is that we need good statistics for individual podcasts ...
and we want to make it more mobile/tablet friendly as well ..

audio module stats weren't the greatest and most detailed, but wondering if anyone has good info on how to provide good stats per podcast(taxonomy and/or user).

love to hear from ya and thanks for all the great work

Hi! I started using Drupal a

4

Hi!

I started using Drupal a few months ago (Drupal 6)
It works fine for me but I hear Drupal 7 is better in some ways.
I want to switch to Drupal 7 now but I think I am going to need a tutorial or something
because it is harder to use (so they say)
Could you guys recommend me a tutorial or something?

yours, family tree maker developer

Batch API solves this problem

3

Hi Guys,

The right way to upgrade from the D6 audio module to D6 audiofield module is by creating a custom drupal module (not just a script) that can do the upgrade using the Batch API to prevent PHP timeouts.

I have an example module you can use to do this migration, but you may need to make some changes to the destination content type to suit your needs, so don't use it on a production site. Test first.

http://drupal.org/sandbox/jenlampton/1761334

Interesting timing

5

Jen,

Interesting timing on your comment. I've been working on an import from a legacy podcast to Drupal for a similar project where I don't have command-line access to the server, so I was going to write my own handling to avoid PHP timeouts. This might be a simpler solution. I'll check it out.

Thanks!
Micah

Awesome! Here's how you do it using VBO

5

Instead of using a script I just used VBO (Views Batch Operations) and it seemed to work super well. Thanks for your script :)

$object->type = 'multimedia';

  // Migrate the audio file to filefield
  $object->field_event_audio[] = array(
'fid' => $object->audio['file']->fid,
'list' => 1, // Set to 1 to display on the node or 0 to hide.
'uid' => $object->audio['file']->uid,
'filename' => $object->audio['file']->filename,
'filepath' => $object->audio['file']->filepath,
'filemime' => $object->audio['file']->filemime,
'filesize' => $object->audio['file']->filesize,
'status' => $object->audio['file']->status,
'timestamp' => $object->audio['file']->timestamp,
  );
  // Remove the audio module informaion.
  unset($object->audio);

  // Save the changes
  node_save($object);