Ruby URL safe base62 string like youtube
http://ronny.haryan.to/archives/2009/04/07/build-your-own-url-shortening-service/#more-191
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class BaseCodec def self.base_n_decode(s, alphabets) n = alphabets.length rv = pos = 0 charlist = s.split("").reverse charlist.each do |char| rv += alphabets.index(char) * n ** pos pos += 1 end return rv end def self.base_n_encode(num, alphabets) n = alphabets.length rv = "" while num != 0 rv = alphabets[num % n, 1] + rv num /= n end return rv end end class Base62 < BaseCodec ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" def self.decode(s) base_n_decode(s, ALPHABETS) end def self.encode(s) base_n_encode(s, ALPHABETS) end end |
Port install FFmpeg updated.
cd /opt/local/var/macports/sources/rsync.macports.org/release/ports/multimedia/ffmpeg
vi PortFile
7 configure.cflags-append DHAVE_LRINTF ${configure.cppflags}-disable-mmx \
78 configure.args \
79 —disable-vhook \
80 —enable-gpl \
81 —enable-postproc \
82 —enable-swscale —enable-avfilter —enable-avfilter-lavf \
83 —enable-libmp3lame \
84 —enable-libvorbis \
85 —enable-libtheora \
86 —enable-libdirac —enable-libschroedinger \
87 —enable-libfaac \
88 —enable-libfaad \
89 —enable-libxvid \
90 —enable-libx264 \
91 —mandir=${prefix}/share/man \
92 —enable-pthreads \
93 —enable-nonfree \
94 —enable-libamr-nb —enable-libamr-wb \
95 —cc=gcc-4.0
96 #
http://www.penguin.cz/~utx/amr
get libamrnb and libamrwb
downgrading lame to 3.97
Quick guide to Amazon EBS
We’ve switched to use Amazon EBS for a few months now. Therefore, we have been able to have a good night’s sleep without worrying our database disappearing. Here’s a quick guide.
It’s very easy to use EBS for EC2. First make sure you downloaded the latest ec2-api-tools (you can’t find EBS related tools in its old version). Here’s my ec2-api-tools info (yours don’t need to be exactly same with me):
—- ruby $ ec2ver
1.3-24159 2008-05-05
—-
EC2 instance can only use EBS in the same avaliablity zone with it, so we need to check the availability zone in which your ec2 instances are. You can do this by
$ ec2din
…
INSTANCE i-abc12345 ami-abc12345 ec2-…compute-1.amazonaws.com ip-….ec2.internal running 0 m1.small 2008-06-23T23:12:26+0000 us-east-1b
So the instance is in us-east-1b. Now create a 200G storage block in this zone:
—- ruby$ ec2-create-volume —size 200 -z us-east-1b
VOLUME vol-4d826724 200 creating 2008-10-14T00:00:00+0000
1 2 3 4 5 6 |
You can check the block by<br /> <br /> --- ruby$ ec2-describe-volumes vol-4d826724 VOLUME vol-4d826724 200 available 2008-10-14T00:00:00+0000 |
The block now is created. It’s like we have bought a 200G harddisk from amazon, now let’s install it on our ec2 instance:
—- ruby$ ec2-attach-volume vol-4d826724 -i i-6058a509 -d /dev/sdh
ATTACHMENT vol-4d826724 i-6058a509 /dev/sdh attaching 2008-10-14T00:15:00+0000
1 2 3 4 5 6 7 8 |
This will let the system on ec2 instance recognize our new block storage on /dev/sdh (you can specify any device name that not the same with currently used, like /dev/sdz). Now you can use this device (/dev/sdh) as a normal block device like other real disk partitions(such as /dev/sda). For example,<br /> <br /> --- ruby$ mkreiserfs /dev/sdh #this will format it with reiserfs $ mkdir /mnt/data $ mount /dev/sdh /mnt/data #mount the block to /mnt/data, now all data write to /mnt/data dir will be # persistent on the block storage vol-4d826724. it won't lost after you reboot the machine |
Some other useful tools are:
ec2-describe-volumes: used to find the relationships between your blocks and instances
ec2-detach-volume: detach a block from instance
Here’s a full manual of EBS.
Download youtube videos with ruby
As you might know, we’ve released Ankoder.net for while now. It lets anyone to download videos into their iPods and various other formats. Scraping the flv url from Youtube HTML isnt exactly easy.
This is how we do it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def parse_youtube(url) youtube = "http://www.youtube.com/" # url =~ /(?:http\:\/\/.*youtube.com\/(?:watch\?v=|v\/))?(.*)$/ url =~ /watch\?v=(.*)/ video_id = $1 video_id = video_id.split("&")[0] flv_url = nil open("#{youtube}watch\?v=#{video_id}") do |f| f.each_line do |line| if line =~ /watch_fullscreen\?(.*?)video_id=([\w-]+)&(.*?)&t=([\w-]+)&/ # p line flv_url = "#{youtube}get_video?video_id=#{$2}&t=#{$4};auto" break end end end flv_url end USER_AGENT = %{Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.11) Gecko/20071231 Firefox/2.0.0.11 Flock/1.0.5} IO.popen("curl -o \"#{file_name}\" -L -A \"#{USER_AGENT}\" \"#{parse_youtube(url)}\" 2>&1") |
Uploading large files to Rails with Merb
As you know Rails does bad on handling file upload, a large file will block your Rails app a long while, make it busy on receiving the file and can’t give response to other visitors, make them upset and leave you alone.
One solution is using merb to handle file upload for rails. The latest Merb that build on Rack(a cool framework who help you dealing with all kinds of http servers) does a really good job on uploading.
First, install merb:
—- rubysudo gem install merb
1 2 3 4 5 6 7 |
Second, create a merb app in your rails dir:
--- ruby
merb-gen app uploader
cd uploader
|
You can ignore all other files except config/rack.rb, this is the only file we need to modify.
Currently there’s only one line in the file:
1 |
run Merb::Rack::Application.new |
It will ask merb to handle the http request come from rack.
Let us change this file to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
require 'cgi' class File def to_s path end end # build a new handler to handler rack's request class Uploader def call(env) # leverage merb's utility to parse the request. # Merb will save the file to a tempfile and save the tempfile's path in request's param request = Merb::Request.new(env) params = request.params # pass the params directly to the real (rails) app result = post("http://someplace.com/api", hash_to_params(params)).split("\n")[-1] # processing result or just ignore it ... end private def post(url, params="") curl_cmd = "curl -H \"Content-type: application/x-www-form-urlencoded\" #{url} -d \"#{params}\"" puts "curl_cmd = #{curl_cmd}" f = IO.popen(curl_cmd +" 2>&1") result = f.read f.close result end def hash_to_params(hash) hash.map do |k, v| if v.kind_of? Hash h = {} v.each { |kk, vv| h["#{k}[#{kk}]"] = vv } hash_to_params h else "#{k}=#{CGI.escape v.to_s}" end end.join("&") end end run Uploader.new |
Run merb by
merb p 1234 -c 1 -e production -d-
-
Remember to config your apache or your favorite webserver to redirect all request from /uploader to port 1234 (Your merb uploader is listening here!).
Pretty easy, isn’t it?
The Facebook autocomplete address to: field.
We’ve extended the Autocomplete.Local from Scriptaculous to implement the autocomplete to: field mimicing the Facebook’s features. This was a little challenging at the start, but prototype.js and scriptaculous have just made it so much easier.

Concepts
- json – array of contacts with names and email address and any other fields you wish to search
- The input box changes size dynamically and reposition itself according to the keystrokes
- Each ‘token’ created is an input field, submitting the id of the user or an email address
Straight to the source
Syntax
1 |
new Autocompleter.LocalAdvanced(id_of_text_field, id_of_div_to_populate, json_array, options)
|
The constructor takes four parameters. The first two are, as usual, the id of the monitored textbox, and id of the autocompletion menu. The third is an array of strings that you want to autocomplete from, and the fourth is the options block.
Extra local autocompletion options
| Option | Default Value | Description |
|---|---|---|
search_field |
“name” | Which attribute to search in the json array. |
choices |
10 | How many autocompletion choices to offer |
partialSearch |
off | If false, the autocompleter will match entered text only at the beginning of strings in the autocomplete array. Defaults to true, which will match text at the beginning of any word in the strings in the autocomplete array. If you want to search anywhere in the string, additionally set the option fullSearch to true |
fullSearch |
false | Search anywhere in autocomplete array strings. |
partialChars |
2 | How many characters to enter before triggering a partial match (unlike minChars, which defines how many characters are required to do any match at all). |
ignoreCase |
true | Whether to ignore case when autocompleting |
Example
HTML
1 2 3 4 5 6 7 8 9 10 |
<div tabindex="-1" id="ids" class="clearfix tokenizer" onclick="$('autocomplete_input').focus()"> <span class="tokenizer_stretcher">^_^</span><span class="tab_stop"><input type="text" id="hidden_input" tabindex="-1"></span> <div id="autocomplete_display" class="tokenizer_input"> <input type="text" size="1" tabindex="" id="autocomplete_input" /> </div> </div> <div id="autocomplete_populate" class="clearfix autocomplete typeahead_list" style="width: 358px; height: auto; overflow-y: hidden;display:none"> <div class="typeahead_message">Type the name of a friend, friend list, or email address</div> </div> |
Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
(new Image()).src='/inbox/images/token.gif'; (new Image()).src='/inbox/images/token_selected.gif'; (new Image()).src='/inbox/images/token_hover.gif'; (new Image()).src='/inbox/images/token_x.gif'; var contacts = [ {name:"phoenix zhuang",email:"phoenix@rorcraft.com"}, {name:"jian xie",email:"jan.xie@rorcraft.com"}, {name:"isaiah peng",email:"isaiah.peng@rorcraft.com"}, {name:"chris chan",email:"chris.chan@rorcraft.com"}, {name:"rex chung",email:"rex@rorcraft.com"}, {name:"chung rex",email:"chung@rorcraft.com"}, {name:"chan chris",email:"chan@rorcraft.com"}, {name:"peng isaiah",email:"peng@rorcraft.com"} ]; var typeahead = new Autocompleter.LocalAdvanced('autocomplete_input', 'autocomplete_populate', contacts, { frequency: 0.1, updateElement: addContactToList, search_field: "name" }); var hidden_input = new HiddenInput('hidden_input',typeahead); |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/* autcompleter.advancedlocal css */ .tokenizer{min-height:5px;padding:0px 0px 3px 3px;width:100%;background:#fff;font-size:11px;} .tokenizer_locked{background:#f4f4f4;} .tokenizer, .tokenizer *{cursor:text} .tokenizer input{width:100%;} .tokenizer .tokenizer_input, .tokenizer .token{float:left;margin-right:3px;margin-top:3px;} .tokenizer .tab_stop, .tokenizer .tokenizer_stretcher{display:block;float:left;overflow:hidden;width:0px;} .tokenizer .tab_stop{height:0px;} .tokenizer .tokenizer_stretcher{padding-top:7px;} #autocomplete_input{width:20px;} #facebook .tokenizer .tab_stop input{border:0px solid black;display:inline;position:relative;left:-500px;} #facebook .tokenizer .tokenizer_input_borderless {left:4px;margin-left:-1px;overflow:hidden;position:relative;} #facebook .tokenizer_input_borderless #autocomplete_input{border:3px solid white!important;border-left:none;display:block;margin:-3px 3px -4px -2px;padding:0px!important;} /*IE6-/Win only*/ /*\*/ * html#facebook .tokenizer_input_borderless #autocomplete_input { border:3px solid black;margin: -3px 3px -4px 14px:padding-left:10px; } /**/ .tokenizer div:-moz-first-node{padding-top:1px!important;} .tokenizer_input{max-width:450px;overflow:hidden;padding:1px 0px;} #facebook .tokenizer_input input, .tokenizer_input_shadow{border:0px solid black;outline:0;font-family:'lucida grande', tahoma, verdana, arial, sans-serif;font-size:11px;padding:0px 5px;margin:0 0 -1px 0;white-space:pre;} .tokenizer_input_shadow{display:inline;left:-10000px;position:absolute;top:-10000px;} .tokenizer .tokenizer_input_shadow{height:0px;display:block;left:0px;overflow:hidden;position:relative;top:0px;} div.tokenizer .token{background-image:url('/inbox/images/token.gif');background-repeat:no-repeat;color:black;white-space:nowrap;} div.tokenizer .token span{background-image:url('/inbox/images/token.gif');background-position:top right;background-repeat:no-repeat;display:block;} div.tokenizer .token span span{background-position:bottom right;} div.tokenizer .token span span span{background-position:bottom left;} div.tokenizer .token span span span span{background-image:none;padding:2px 3px 2px 5px;} div.tokenizer.tokenizer_locked .token span span span span{padding-right:5px;} html div.tokenizer_locked .token:hover, html div.tokenizer_locked .token:hover span{background-image:url('/inbox/images/token.gif');} div.tokenizer .token:hover, div.tokenizer .token:hover span{background-image:url('/inbox/images/token_hover.gif');text-decoration:none;} div.tokenizer .token_selected, div.tokenizer .token_selected span, div.tokenizer .token_selected:hover, div.tokenizer .token_selected:hover span{background-image:url('/inbox/images/token_selected.gif');color:white;text-decoration:none;} div.tokenizer .token span.x, div.tokenizer .token span.x_hover, div.tokenizer .token:hover span.x, div.tokenizer .token:hover span.x_hover{background-image:url('/inbox/images/token_x.gif');background-position:4px 2px;cursor:pointer;display:inline;padding:0px 6px 0px 5px;} div.tokenizer.tokenizer_locked .token span.x, div.tokenizer.tokenizer_locked .token span.x_hover{display:none;} div.autocomplete { position:absolute; width:355px; background-color:white; border:1px solid #888; margin-top:-2px; padding:0px;} div.autocomplete ul { list-style-type:none;margin:0px; padding:0px;} div.autocomplete ul li.selected { background-color: #ffb;} div.autocomplete ul li { list-style-type:none; display:block; margin:0; padding:2px; height:32px;cursor:pointer;} /* end of autcompleter.advancedlocal css */ |
Download the full source
Autocomplete_AdvancedLocal.zip
[update] We’ve forked a version of the control.js and changed all reference to element.style to setStyle(). It was causing script errors in IE.
http://github.com/rorcraft/scriptaculous/tree/master/src/controls.js
Patching paperclip to create thumbnails only for images
Paperclip has some good features over attachment_fu that “attached files don’t need to have a seperare model (thank god). Your attachments are treated just like any other atribute. Images aren’t saved until your model is saved” ( by Jim Neath ).
The fall back of paperclip is that it tries to create a thumbnail for any type of file, including pdf. It won’t cause much problem if it cannot create a thumbnail to a certain file. But when it comes to pdf file, paperclip tries to generate a thumbnail for every page of the file, it becomes very slow when uploading the pdf file if the file has hundreds of pages. Sometimes it even times out! At the same time, attachment_fu does not have this problem.
attachment_fu.rb includes a class method #images? to distinguish if the file is an image.
—- ruby129 # Returns true or false if the given content type is recognized as an image.
130 def image?(content_type)
131 content_types.include?(content_type)
132 end
1 2 |
<p>Content types of images are initialized at the begin of the file:</p> --- ruby5 @@content_types = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg'] |
Then the #image? method is called in a instantial method #thumbnailable:
1 2 3 4 5 6 7 8 9 10 |
216 # Checks whether the attachment's content type is an image content type
217 def image?
218 self.class.image?(content_type)
219 end
220
221 # Returns true/false if an attachment is thumbnailable.
# A thumbnailable attachment has an image content type and the parent_id attribute.
222 def thumbnailable?
223 image? && respond_to?(:parent_id) && parent_id.nil?
224 end
|
In the #create_or_update_thumbnail it test if the content is thumbnailable? to determine going or not.
—- ruby243 # Creates or updates the thumbnail for the current attachment.
244 def create_or_update_thumbnail(temp_file, file_name_suffix, *size)
245 thumbnailable? || raise(ThumbnailError.new(“Can’t create a thumbnail if the content \
type is not an image or there is no parent_id column”))
246 returning find_or_initialize_thumbnail(file_name_suffix) do |thumb|
247 thumb.attributes = {
248 :content_type => content_type,
249 :filename => thumbnail_name_for(file_name_suffix),
250 :temp_path => temp_file,
251 :thumbnail_resize_options => size
252 }
253 callback_with_args :before_thumbnail_saved, thumb
254 thumb.save!
255 end
256 end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<p>Paperclip has a similar structure like this, it makes it easier to make this patch.</p>
--- rubyFrom line #217
def post_process #:nodoc:
return if @queued_for_write[:original].nil?
logger.info("[paperclip] Post-processing #{name}")
@styles.each do |name, args|
begin
dimensions, format = args
dimensions = dimensions.call(instance) if dimensions.respond_to? :call
@queued_for_write[name] = Thumbnail.make(@queued_for_write[:original],
dimensions,
format,
@whiny_thumnails)
rescue PaperclipError => e
@errors << e.message if @whiny_thumbnails
end
end
end
|
The trick here is to add the #thumbnailable? method in right after the #begin keyword and raise a PaperclipError if it fails:
—- ruby213 def post_process #:nodoc:
214 return if queued_for_write[:original].nil?
215 @styles.each do |name, args|
216 begin
# Test here
217 thumbnailable? || raise(PaperclipError.new("Can not create thumbnails \
if the content type is not an image."))
218 dimensions, format = args
219 dimensions = dimensions.call(instance) if dimensions.respond_to? :call
220 @queued_for_write[name] = Thumbnail.make(queued_for_write[:original],-
221 dimensions,
222 format,-
223 @whiny_thumnails)
224 rescue PaperclipError => e
225 @errors << e.message if @whiny_thumbnails
226 end
227 end
228 end
—-
Add the #image? and #thumbnailable? method to attachment.rb of paperclip, and initialize the thumbnailable content types at the beginning. That’s all, now you can upload pdf files very fast.
About how to use paperclip, Jim Neath has a great tutorial Paperclip: Attaching Files in Rails. Enjoy it!
Using XSendFile to prevent memory leak in mongrel
When we working on the lastest project which allow user to download video that may be upto a few hundred MB, we see that the memory usage of mongrel start from 5MB in the beginning , and jump to to 300MB in a single night. After trace for a while, we found that the source of the leaking pointing to sendfile function that we currently use. So we looking for a solution to fix the memory leak , and that is the XSendFile which we are going to talk about.
Most of the people would use mongrel as the application server to deploy the rails , while using apache as the load balance proxy to forward the traffic to the servers that running mongrel. By using XSendFile, instead of mongrel load the file , and pass the file stream to apache,
Amazon EC2 finally support static IP addresses
To enable the static IP addresses function , you need to download the latest Amazon EC2 Command-Line Tools,
the download link of it is http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351&categoryID=88
after download, I recommend to unzip it to a folder call ec2 under your home path
—- htmlmkdir /ec2
cd ~/ec2
unzip ec2-api-tools.zip—-
you can now see a folder call ec2-api-tools-1.3-19403 under the ec2 folder.
now it is time to update the .profile , so that EC2 tool can find the library that it use.
you have to download the private and public cert from amazon
—- htmlnano ~/.profile
export PATH=/ec2/ec2-api-tools-1.3-19403/bin:$PATH
export EC2_HOME=~/ec2/ec2-api-tools-1.3-19403
export EC2_CERT=~/.ec2/cert-xxxxxxxxx.pem
export EC2_PRIVATE_KEY=~/.ec2/pk-yyyyyy.pem—-
then you can start a new console so that the profile update will be effective.
you can now allocate a new IP address for your account.
—- htmlChris:~ chrischan$ ec2-allocate-address
ADDRESS 75.101.139.212—-
This new IP 75.101.140.212 is not bundle to any AMI instance yet.
You have to manually assign this IP address to a instance
First, you need to know the instance that you have already started. you can use the following command
—- htmlChris:~ chrischan$ ec2-describe-instances
RESERVATION r-3c1bea55 073126868754 default
INSTANCE i-7124dd30 ami-5035d079 ec2-67-202-34-115.compute-1.amazonaws.com
domU-12-31-38-00-6D-98.compute-1.internal running 0m1.small 2008-03-05T15:51:36+0000
us-east-1a—-
you can see that the instance id is i-7124dd30, we can then assign the IP to that instance
—- htmlChris:~ chrischan$ ec2-associate-address 75.101.140.212 i i-7124dd30—
ADDRESS 75.101.140.212 i-7124dd30
If you want to check the address allocation status, you can use the follow command
—- htmlChris:~ chrischan$ ec2-describe-addresses
ADDRESS 75.101.140.212 i-7124dd30—-
for any time if you want to free the IP , you can use
—- htmlec2-release-address IP-address—-
If you want to assign the existing IP address to a new instance , you can use ec2-associate-address,
but this time , you assign the new instance IP, and the existing IP address bundling will remove,
so the single IP address will always only bundle to one instance.
Also, a instance can only have one IP address assocate to it , so when you assign a new IP address to a instance,
all the existing IP bundling will be removed. And all the IP address in this status will start to charge you account.
So whenever any IP allocate has finished , please make to use ec2-describe-addresses to check the IP address bundling status.
Ankoder Architecture presentation
In March, we had a ruby on rails user group meetup in Hangzhou, China. It was exciting to meet more rails developers in China and shares some experience on our projects. Hangzhou is famous for it’s West Lake, it is just 1.5 hrs south of Shanghai. It is turning into the Silicon Valley of China, because several large internet companies are based in Hangzhou, such as Alibaba. They are also experimenting with Rails, because of its amazing productivity gains.
<img src=“http://devblog.rorcraft.com/assets/2008/3/28/IMG_1903.JPG”/ width="400">
We did a presentation on our architecture and how we host a fault tolerant system on Amazon’s EC2. We will already need to change this a little since Amazon has just released the long been waited feature Static IP. Now you don’t need to rely on DNS to failover to your new server, you can at least start a new instance and point your IP to the new host.
MySQL - scaling options
On our quest to setup a stable MySQL system, we’ve got some tips that we want to share with our fellow developers.
First you need to be clear about your requirement. Load balancing and fault tolerant setup are two different things.
Also note that MySQL replication is different to clustering.
For Load balancing you will want to distribute MySQL access to two or more servers.
For fault tolerant architecture you will need two or more servers but not necessarily using both servers at the same time to balance load.
Master Slave
Master Master
Clustering
- MySQL 5.0 – memory only
- MySQL 5.1 – not stable
Other options:
memcachedb
Ankoder API ruby library released
Do you need to build a mini youtube for your client?
Do you want to include video functionalities to your site?
We’ve released the ruby library that we are already using on http://free.ankoder.com both in rails plugin form as well as ruby gem form.
Install it and have a look at the rdoc
Rails Plugin
1 |
script/plugin install http://ankoder.googlecode.com/svn/trunk/trunk/ankoder_on_rails
|
Ruby Gem
http://rubyforge.org/projects/ankoder/
1 2 3 4 5 6 |
$ sudo gem install ankoder Password: Bulk updating Gem source index for: http://gems.rubyforge.org Successfully installed ankoder-0.0.2- Installing ri documentation for ankoder-0.0.2-... Installing RDoc documentation for ankoder-0.0.2-... |
Send us an email if you’re keen to try it.
We’re working on our payment model and cleaning up the UI so you can manage your services.
mpeg4aac for ffmpeg problem
Error Message:
[mpeg4aac @ 0xb7d7a748]FAAD library: cannot resolve faacDecGetErrorMessage in libfaad.so.0!
Solution:
First you should comfirm that libfaad.so.0 library is located in the path which are defined by the LD_LIBRARY_PATH environment variable. Otherwise, you can use
export LD_LIBRARY_PATH=/home/ffmpeg/usr/local/lib
to add the libfaad.so.0 to the LD_LIBRARY_PATH. (in this case, libfaad.so.0 is in the /home/ffmpeg/usr/local/lib ).
Second, Modify libavcodec/libfaad.c in ffmpeg source code
change line:
do { static const char* n = "faacDec" #a; \
To:
do { static const char* n = "NeAACDec" #a; \
change line:
#define dfaac(a, b) s→faacDec ## a = faacDec ## a
To:
#define dfaac(a, b) s→faacDec ## a = NeAACDec ## a
Re-compile ffmpeg.
Step by step guide to preparing EC2 on MacOSX
Amazon provides two types of tool.
1. Operational tools that use to startup and shutdown AMI instances
2. Packaging tool to pack the AMI that created , or modify on existing public AMI and rebundle to new private AMI
Operational tool
Create a new AWS Access Identifiers if you don’t already have.
$ mkdir ~/.ec2
download both the Private Key file and X.509 Certificate file to ~/.ec2
rename the pk-xxxxxxxxxx.pem one to PrivateKey.pem
rename the cert-xxxxxxxxx.pem one to 509certificate.pem
( xxxxxxxxxx stand for the random name generate by amazon )
visit the following to download the packaged file to Download folder
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351&categoryID=88
$ mkdir ~/ec2
$ cp ~/Downloads/ec2-api-tools.zip ~/ec2/
$ cd ~/ec2/
$ unzip ec2-api-tools.zip
$ nano ~/.profile
append the follow line to the end
export JAVA_HOME=/Library/Java/Home
export PATH=~/ec2/ec2-api-tools-1.2-13740/bin:$PATH
export EC2_HOME=~/ec2/ec2-api-tools-1.2-13740
export EC2_PRIVATE_KEY=~/.ec2/PrivateKey.pem
export EC2_CERT=~/.ec2/509certificate.pem
restart the terminal to active the changes on bash profile
$ ec2-describe-images -o amazon
IMAGE ami-20b65349 ec2-public-images/fedora-core4-base.manifest.xml amazon available public
IMAGE ami-22b6534b ec2-public-images/fedora-core4-mysql.manifest.xml amazon available public
IMAGE ami-23b6534a ec2-public-images/fedora-core4-apache.manifest.xml amazon available public
IMAGE ami-25b6534c ec2-public-images/fedora-core4-apache-mysql.manifest.xml amazon available public
IMAGE ami-26b6534f ec2-public-images/developer-image.manifest.xml amazon available public
IMAGE ami-2bb65342 ec2-public-images/getting-started.manifest.xml amazon available public
IMAGE ami-36ff1a5f ec2-public-images/fedora-core6-base-x86_64.manifest.xml amazon available public
IMAGE ami-bd9d78d4 ec2-public-images/demo-paid-AMI.manifest.xml amazon available public A79EC0DB
If install sucessfully , will show the list of the AMI that amazon provide
$ ec2-add-keypair demo-keypair
KEYPAIR ankoder d9:d9:85:95:5f:ef:19:c9:33:5b:78:e6:e7:82:cc:e2:6a:9f:70:76
——-BEGIN RSA PRIVATE KEY——-
MIIEowIBAAKCAQEAyfG40k8HRgFaZZqDUQu5FZAjyKFDOKgMLb0DpmP10oM3RCz4KBqHQfJgyjqs
5cz++qG1NDQ1HYVs7Ke45OshRU+ibIvRh57L1EcRetEerpXNZJ3qKkcj+wMvyAhEYo515DKCQbWG
+M8SVNDTdXDIFAZBxs2Bo9wvrbRn8J+cCyqRSkYl+CpfIen8LcU0TD6ssCASIaUW++z+Sj0iH9p/
+PirmSWhbEbFqgYNqUPrIuNitSYE1wEsPF+ckHuL18Vn7Zc4gMM9eOQ4+u+NgGpPMAs8ZY8Fu7tJ
Oq2pZQhHI3E18QVh7/CkRNl7quYGm+WQUermSycFNOABU6+KEWdoYwIDAQABAoIBAAp9L6hcynfs
YhGc8O0ourhQAEvPdHpg4CEQDDx8PKxufFRiMZGDrzrRqA1Y9toIx8Wk2JCZlZiu8XVpUMUzIUtE
U59ns75jlRq1hkbmzb0rsrtjKGKBx3CmPbkaFNM5qw3rQbDACP6rYrxdDF6xOPMxUAFPc0hbi25u
TGfHIofB2npVu5YxqHUambJI/mgbXMIU5xuZ0Ha1ALYM4dtG66q1HzpYTPw+DXh+PtpgIKFBuL7K
6WZpaX3Z5ll9JbYclnxIjnZProeZa4Hty5/ND1TbeMWfi9e1TLXbpP02Um0pTCxE8kdmkqqtfg3
t6CW39zY53jxmPS2HWTVzSM3V4ECgYEA/3UnllaaPZY1XmQ81lz4Fia4w4z/SjBjB6FY1s5qkfnD
tBVCRs1anxf8nKI75GGYlogV77iKPKMbWmhM2Jj6dnMbtfpPfpGzUgPrkccMeRTv/XpfMuT1hh+
p2NLHfld7/7MLC+AidrBZxryfwo/Fa6v+aJg4KnFDx+UDxmUx/MCgYEAyl97Xue4nsfw3v/HfNYs
pvkvQ7aSPd16XU+6fKQa4FZi2N8Soiz7qiOoBjBSGoFW5EF5Ai7i56RLGDqXHNXd8WnduhflFc2l
jtzifP1DFDsyR+dYbblT7b5DW2WntXTVsAk3Xn+oGcriL2qFvbGmce9H1fVnPaOKsZsMl3g86dEC
gYEAvQWGFlKFHGEB+mc3MPK3y0Q5oNC6sb2d+S5lGwS/jGYAbkbwtI0Myf2ouIm+wV2KIW0A04x1
shDO4cKwOeJKxeWXxEjU2DxRmWIB4FXTwgMOCVM/wkyshlW3mcn58iLrZELn9qXreZW5V75zwpbl
WPjaU1/YSUS1gFxAZO/rzAsCgYA3/w+OBSQqmzxlF/VE76ZPVWfknqH8iEoRg7wgPPBK3txfEeqA
AV5ph5A4lipBt0QpyIwJNJwIaId23s9tZSgSYq69jVsQG2USEMCCwTlMYczZ5IOtaLh2ck0E/y3W
oct2+DXf6gbDjEXlxN3YzU02/XStGUhF3/kCiBqF1vlT4QKBgFtaVjtc1VO/t0+vQ8CmTn4Y03Ml
pCORn4081m1w5PhfEbei+qzAY66r8AkB1Du9CT/NhrGXMsTTrsTiaApjoJ2HMUW3Pr/m6x/QIpTf
/4cFSHaDKnb5plNB3+DwPjjtDx/37PC6XAVTOPxaANr/lEkkST0vub+MkkQ/RxShLxKg
——-END RSA PRIVATE KEY——-
copy the above text including -—BEGIN RSA PRIVATE KEY——- and -—END RSA PRIVATE KEY——-
to ~/.ssh/id_rsa-demo-keypair
$ nano ~/.ssh/id_rsa-demo-keypair
paste all the content to it and save
$ ec2-run-instances ami-25b6534c -k demo-keypair
RESERVATION r-b7fc17de 119012238391 default
INSTANCE i-6ea05007 ami-25b6534c pending ankoder 0 m1.small
2008-01-07T05:49:15+0000
if the terminal return the message similar to this , you have successfully started a AMI instance.
To show all the instances currently running can use the ec2-describe-instances command
$ ec2-describe-instances
INSTANCE i-6ea05007 ami-25b6534c ec2-67-202-24-116.compute-1.amazonaws.com
domU-12-31-38-00-29-48.compute-1.internal running ankoder m1.small
2008-01-07T05:49:15+0000
To shutdown a running instance, can first find the instance id by using `ec2-describe-instances` , the one that in format of i-xxxxxxxx is the instance id
$ ec2-terminate-instances i-6ea05007
INSTANCE i-6ea05007 running shutting-down
Allow the instance to be accessable from outside
$ ec2-authorize default -p 22
PERMISSION default ALLOWS tcp 22 22 FROM CIDR 0.0.0.0/0
$ ec2-authorize default -p 80
PERMISSION default ALLOWS tcp 80 80 FROM CIDR 0.0.0.0/0
$ ec2-authorize default -p 21
PERMISSION default ALLOWS tcp 80 21 FROM CIDR 0.0.0.0/0
To connect to the AMI instance from SSH
first check the hostname
$ ec2-describe-instances
INSTANCE i-55a0503c ami-25b6534c ec2-67-202-2-199.compute-1.amazonaws.com
domU-12-31-38-00-42-55.compute-1.internal running ankoder m1.small
2008-01-07T06:02:38+0000
using the private key that you generated to login
$ ssh root@ec2-67-202-2-199.compute-1.amazonaws.com -i ~/.ssh/id_rsa-demo-keypair
you can do whatever you like in this instance
install ec2onrails support tool
$ sudo gem install ec2onrails
As the Amazon EC2 tool is in rpm format, and MacOSX doesn’t come with it.
so we have to use DarwinPorts to install rpm first
Install the rpm
$ sudo port install rpm
Install Amazon packaging tool
$ wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm
$ sudo rpm -i ec2-ami-tools.noarch.rpm —nodeps —ignoreos
Also, there is a gem for access the EC2 from ruby
$ sudo gem install amazon-ec2 —include-dependencies
Generate PDFs in Rails with RFPDF
1, Install railsrfpdf plugin
ruby script/plugin install http://cnruby.googlecode.com/svn/trunk/rails-projects/infoq_rfpdf/vendor/plugins/railsrfpdf/
2, add new Mime type to environment.rb:
Mime::Type.register “application/pdf”, :pdf
3, in the controller:
—- rubyrespond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @page.to_xml }
format.pdf do
pdf = FPDF.new
pdf.AddPage
pdf.SetFont(“Arial”,‘B’,18)
pdf.Cell(100, 20, “Hello World”)
send_data pdf.Output, :filename => “hello.pdf”, :type => “application/pdf”
end
end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<img src="http://devblog.rorcraft.com/assets/2007/12/19/hello.png" />
<strong>Useful method in RPDF</strong>
SetFont(string family [, string style [, float size]])
SetMargins(float left, float top [, float right])
SetTextColor(int r [, int g, int b])
SetXY(float x, float y)
AddFont(string family [, string style [, string file]])
Cell(float w [, float h [, string txt [, mixed border [, int ln [, string align [, int fill [, mixed link]]]]]]])
Image(string file, float x, float y [, float w [, float h [, string type [, mixed link]]]])
Line(float x1, float y1, float x2, float y2)
MultiCell(float w, float h, string txt [, mixed border [, string align [, int fill]]])
Rect(float x, float y, float w, float h [, string style])
<strong>A case in real world</strong>
<macro:code lang="ruby">
pdf = FPDF.new('portrait', 'pt', [800, 1380])
pdf.SetAutoPageBreak(false)
pdf.AddPage
# draw a rectangle
pdf.SetFillColor(240, 240, 240)
pdf.Rect(0, 0, 800, 895, 'F') pdf.Image("#{RAILS_ROOT}/public/images/a.jpg", 0, 0, 800, 600)
# add four images
pdf.Image("#{RAILS_ROOT}/public/images/b.jpg", 0, 700, 260)
pdf.Image("#{RAILS_ROOT}/public/images/c.jpg", 270, 700, 260)
pdf.Image("#{RAILS_ROOT}/public/images/d.jpg", 540, 700, 260)
# write text
txt = 'Agile Web Development'
pdf.SetFont("Arial", 'B', 38)
pdf.SetXY(0, 600)
pdf.Cell(800, 100, txt, 10, 1, 'C')
pdf.SetTextColor(10, 10, 10)
txt = 'What is Ruby FPDF?'
pdf.SetFont("Arial", 'B', 30)
pdf.SetXY(20, 920)
pdf.Cell(300, 30, txt, 10, 1)
txt = "Ruby FPDF is a Ruby port of Olivier Plathey's excellent PDF generator, /
FPDF. FPDF is written in PHP,
and as such can only be used From PHP scripts. /
Ruby FPDF, as the name suggests, is written in Ruby and /
can be used From Ruby scripts. Ruby FPDF was ported and is maintained by Brian Ollenberger. /
If you need to contact me, see the contact link abovenYou can download Ruby FPDF below. /
It is released under a permissive license, similar to that of FPDF. I only ask that you retain the /
copyright notice at the top of the source file. You may make modifications to FPDF, but if you /
redistribute those modifications, make it clear in a comment immediately before or after the /
copyright notice that you have modified it. I also wouldn't mind if you sent patches back to me, /
but you are not strictly required to do so."
pdf.SetFont("Arial", '', 18)
pdf.SetXY(20, 960)
pdf.MultiCell(500, 20, txt)
txt = 'Ruby | On | Rails'
pdf.SetFont("Arial", '', 24)
pdf.SetXY(540, 920)
pdf.Cell(260, 30, txt, 10, 1, 'C')
#draw rectangle
pdf.SetFillColor(240, 240, 240)
pdf.Rect(550, 960, 230, 300, 'F')
#write text
txt = "* Get Excitednn* Get Startedn* Get BetternnContactnnEnjoy Railsnenjoyrails@gmail.com"
pdf.SetFont("Arial", 'B', 18)
pdf.SetXY(560, 970)
pdf.MultiCell(220, 36, txt)
pdf.SetFillColor(170, 0, 1)
pdf.Rect(0, 1310, 800, 70, 'F')
txt = 'View this page at http://devblog.rorcraft.com/'
pdf.SetTextColor(255, 255, 255)
pdf.SetFont("Arial", '', 28)
pdf.SetXY(0, 1330)
pdf.Cell(800, 24, txt, 0, 0, 'C')
send_data pdf.Output, :filename => "hello_advance.pdf", :type => "application/pdf"
|

Reference:
1: fpdf manual
4: Iconv Rdoc
5: fpdf website
Contact
We love to hear about your web projects.
Email:
Sydney: +61 421 591 943
Hong Kong:+852 6901 2682

