Hi, I'm hosting a podcast using the FileField Podcaster module, which uses GetID3 to automatically retrieve information about each file. I recently switched hosting over to Pantheon (getpantheon.com) and started having issues with the site. The platform is solid, and we eventually narrowed it down to the fact that my podcast view was causing too much strain because GetID3 was parsing each podcast file every time the view was called. Normally, this wouldn't be an issue, but on Pantheon anything 5MB or over written to Pantheon files/ gets streamed to and from S3 instead of the local cluster. This means that everytime GetID3 parses a file it's downloaded for each piece of metadata it needs to get.
For example, if I want to get the file size, length, and title of a podcast file, it has to download the (25MB) file three times. Multiply that by 25 or 50 podcasts in a feed, and you're now downloading 150 files every time the feed is requested... you can see how this could cause a server to slow down quite a bit.
So, their support team suggested a module which stores the id3 info in the database when the file is added. If that could be cached, then the files won't need to be downloaded every time the view is requested.
I believe this would affect anyone using a service like Amazon S3 for file delivery, so I thought I'd bring it up here, and see if we could come up with a solution.
Thanks!
Here are some excerpts from the support issue at Pantheon, just in case they help:
I noticed that your ID3 tag tool does a bunch of seek()s on the file directly. It may be more efficient to copy the file to the local /tmp and then do all the processing there. Those seek() operations seem intended to read as little of the file as possible when a local copy is available, but it turns into loading the full MP3 over the network, possibly multiple times, when on our network file system.
It's not the location of the MP3s as much as how they're processed to get ID3 information. Ideally, MP3s would get uploaded to a temp directory, get their ID3 information extracted there (and pushed into the DB or cache), and then moved to either the Pantheon files/ directory or other storage.
Just so you know, anything 5MB or over written to Pantheon files/ gets streamed to and from S3 instead of the local cluster.
Yes, I think it is that the id3 mod is loading the files into memory to get the info. Josh suggested a module which stores the id3 info in the database when the file is added.
| Comment | File | Size | Author |
|---|---|---|---|
| #11 | cache_id3_info_for-1864762-11.patch | 1.43 KB | travelertt |
| #6 | cache_id3_info_for-1864762-6.patch | 1.42 KB | botris |
Comments
Comment #1
mglamanComment invalid now that 7.x-2.x exists.
Comment #2
MickC commentedI am using 7.x-2.x-dev and find that
a) metadata is not storing in file_metadata if I upload to S3
b) is IS storing if I upload to to Public files
c) if I go to admin/content/file and change a file stored in S3 to Public, it will let me, and then I see data in file_metadata - if I changed it back again to S3 it changed it appended _1 tothe file name, but the metadata was still in the table.
I'm thinking if I can't get metadata to store on the first read into S3, I may have to make public first, then change later.
Although I've been using AmazonS3, "S3 File System" may be better as it is required by a new module "S3 File System Migrate" which is designed to switch filed across using cron.
Comment #3
mglamanMickC, thanks for moving this over here.
I think the original issue was that the original 1.x branch didn't use a database to store ID3 information, it did a pull from the file each time. Later in 1.x this was added. 2.x ditches this table and ties into File Entity (less to maintain, use existing architecture, keep things unified.)
So I think it's appropriate to turn this into attention at the usage of S3 and the module.
To be honest this sounds like a bug with S3 integration, not the module. The module just listens on hook_presave() and analyzes the file. However, I'd be more than willing to debug and poke around - except I don't have access to any S3 storage (I'll see what I can do.)
For now, could you try to see what's happening when using the S3 file scheme versus public?
Comment #4
MickC commentedI switched from "AmazonS3" to the alternative "S3 File System", and also added "S3 File System Migrate".
Same issue if first uploading to S3 so now the plan is to:
- upload to Public
- add a custom module to write metadata values to Audio fields
- schedule cron to migrate to S3 using "S3 File System Migrate"
It's not a solution but a workaround but I think a perfectly acceptable one.
I doubt there'l be any performance penalty, and it may be complex to program a method of integrating with getID3.
The only other thing to possible try is implement "Amazon S3 CORS Upload" https://www.drupal.org/project/amazons3_cors which does the following: "This module works in conjunction with the amazons3 module to provide direct to S3 uploading from your browser. Bypassing the Drupal file system and storing all files in S3 only."
Potentially this method helps Drupal treat S3 as if it was the Public scheme - however this might be something to try at a later date.
Comment #5
botrisSo what I discovered, thanks to codedumperror, in #2500317: S3 File System does not work with Getid3 is that the getid3 does not support stream wrappers. And therefore can only handle local files.
Basically there are two ways around this:
file_create_url()in stead ofdrupal_realpath()Comment #6
botrisA third option would be to download the data from S3 and analyze that data.
Although I think this is not the way to go, I needed to be able to analyze files that where already on the S3 filesystem so attached is a patch that:
This should not be considered a patch that is aiming to make it into the module but a solution you might use for your custom code.
Comment #7
mglamanboris sondagh, thanks for work! Currently on vacation, but will review this on Monday. It is GPL v2 compliant, so if it came to having a bundled and modified library to support remote stream wrappers, so be it - Drupal's tarball handling does this (obviously need to consider issues of bundling.)
Comment #8
dsbrianwebster commentedJust sounding off. I'm using getid3 + amazons3, applied this patch and it worked great! Thanks Boris!
Comment #9
mglamanWhoops didn't realize this wasn't marked for review! If we could get one more person to give it a run and report back with (thumbs up) I'll commit.
Comment #10
botrisJust reviewing the patch again. I'm still using the patch but line 130 could be deleted, as it's after data is being returned.
Comment #11
travelerttOur site is using Storage API and has a different scheme prefix. So I refactored patch #6 to work with any external file with any scheme, after first checking if the file isn't local.
Comment #12
travelerttComment #13
delzhand commented#11 gets a thumbs up from me. Definitely works.
Comment #14
botrisComment #16
mglamanThanks, everyone!
Comment #18
sgdev commentedI'd recommend reviewing this new patch I just created: https://www.drupal.org/project/getid3/issues/3017162
The patch committed in this thread causes a race condition with temp files.