View Single Post
gogol's Avatar
Posts: 177 | Thanked: 57 times | Joined on Aug 2007 @ Washington State, USA
#4
An alternate way to do this that doesn't require bash or wget:
Install links (.40 mb)
Use perl script below. It also works for ifilm.com. Found here (Note: Original script uses lynx instead of links)

Code:
#!/usr/bin/perl
# Filename:	myfilm
# Author:	David Ljung Madison <DaveSource.com>
# See License:	http://MarginalHacks.com/License/
# Description:	Download iFilm/youtube movies given a film ID.
# Converts youtube films from flash to .mov if ffmpeg is available.
  my $VERSION=  '1.02';

use strict;

##################################################
# Setup the variables
##################################################
my $PROGNAME = $0; $PROGNAME =~ s|.*/||;
my ($BASENAME,$PROGNAME) = ($0 =~ m|(.*)/(.+)|) ? ($1?$1:'/',$2) : ('.',$0);

# This will probably change..
my $IFILM = "http://www.ifilm.com/player/mac.jsp?ifilmId=";
my $YOUTUBE = "http://youtube.com/get_video.php?l=165&video_id=";

# How to fetch web files - pick one
# Actual Safari agent example:
# Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/416.12 (KHTML, like Gecko) Safari/416.13
my $GET = "GET -H 'user-agent: Mozilla/5.0'";
my $LYNX = "links -source";

my $GET_URL = $LYNX;

my $POST = "mov";

# For converting youtube to .mov
my $FFMPEG = "ffmpeg";

##################################################
# Usage
##################################################
sub fatal {
	foreach my $msg (@_) { print STDERR "[$PROGNAME] ERROR:  $msg\n"; }
	exit(-1);
}

sub usage {
	foreach my $msg (@_) { print STDERR "ERROR:  $msg\n"; }
	print STDERR <<USAGE;

Usage:\t$PROGNAME [-d] <ifilm URL, youtube URL or ifilm id>
  Download an ifilm movie
  -o <file>         Save to file
  -bw <56,200,300>	Force a bandwidth other than your iFilm settings
  -d                Set debug mode
  -bg               Run ffmpeg in the background

USAGE
	exit -1;
}

sub parse_args {
	my $opt = {};
	while (my $arg=shift(@ARGV)) {
		if ($arg =~ /^-h$/) { usage(); }
		if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; }
		if ($arg =~ /^-bg$/) { $opt->{bg} = 1; next; }
		if ($arg =~ /^-bw$/) { $opt->{bw} = shift @ARGV; next; }
		if ($arg =~ /^-o$/) { $opt->{save} = shift @ARGV; next; }
		if ($arg =~ /^-/) { usage("Unknown option: $arg"); }
		if ($arg =~ m|^http://([^/]+)/.*?([^/]+)$|) { ($opt->{url}, $opt->{dom}, $opt->{film}) = ($arg, $1, $2); next; }
		if ($arg =~ /^[0-9]+$/) { ($opt->{arg}, $opt->{dom},$opt->{film}) = ("ifilm.com", $arg); next; }
		usage("Unknown film id.  I need an iFilm or youtube URL");
	}

	usage("No film URL specified.") unless $opt->{film};
	$opt;
}

sub debug {
	return unless $MAIN::DEBUG;
	foreach my $msg (@_) { print STDERR "[$PROGNAME] $msg\n"; }
}

##################################################
# Utils
##################################################
sub title_embed {
	my ($opt, $url) = @_;

	debug("URL: $url");
	my $open = "$GET_URL $url";
	debug("GET: $open");
	open(FILM,"$open |") || usage("Couldn't get URL: $url\nMake sure [$GET_URL] is installed");
	
	# Find the film location
	my $dl;
	my $title;
	my $bw = $opt->{bw};
	my $embed;
	my $and_t;
	while(<FILM>) {
		$dl = $1 if /var\s+dl\s*=\s*"?(-?\d+)"?/;
		$bw = $1 if !$bw && /var\s+bw\s*=\s*"?(\d+)"?/;
		$embed = $1 if /<embed.*(http:[^>"]+)/i;
		$title = $1 if /span class="title">([^<]+)/;
		$title = $1 if /<title>(.*)<\/title>/;
		$and_t = $1 if /video_id=.*&t=([^&"]+)/;
	}
	close(FILM);
	($title,$embed,$dl,$bw,$and_t);
}

##################################################
# iFilm
##################################################
sub iFilm {
	my ($opt,$film) = @_;

	print STDERR "Fetching iFilm ID: $film\n";

	# Read the ifilm HTML
	my $url = $IFILM.$film;
	my ($title,$smil,$dl,$bw) = title_embed($opt, $url);
	$title = $title || $film;

	usage("Couldn't find 'dl' key in URL [$url]") unless $dl;
	usage("Couldn't find 'bw' key in URL [$url]") unless $bw;
	usage("Couldn't find 'embed' tag in URL [$url]") unless $smil;
	$smil =~ s/'\s+\+\s+dl\s+\+\s+'/$dl/g;
	$smil =~ s/'\s+\+\s+bw\s+\+\s+'/$bw/g;
	$smil =~ s/"$//;
	debug("SMIL: $smil");

	# Get the smil file
	my $open = "$GET_URL \Q$smil\E";
	open(SMIL,"$open |") || usage("Couldn't get SMIL: $smil");
	my $video;
	while (<SMIL>) {
		$video = $1 if /video src="(http[^"]+)"/;
	}
	usage("Couldn't find video source key in SMIL [$smil]") unless $video;
	close SMIL;

	debug("Found: $video");
	$title =~ s/[:\s]+/_/g;
	my $save = $opt->{save} || "$title.$POST";
	$save =~ s|/|_of_|g;
	print "Saving to: $save\n";
	debug("$GET_URL \Q$video\E > \Q$save\E\n");
	system("$GET_URL \Q$video\E > \Q$save\E");
}

##################################################
# youtube
##################################################
sub youtube {
	my ($opt, $film) = @_;
	print STDERR "Fetching youtube ID: $film\n";

	# Get name
	my ($save,undef,undef,undef,$and_t) = title_embed($opt, $opt->{url});
	fatal("No '&t=' code found for youtube [$opt->{url}]") unless $and_t;
	if ($opt->{save}) {
		$save = $opt->{save};
	} else {
		fatal("No title found for youtube [$opt->{url}]") unless $save;
		$save =~ s/youtube( - )?(.+)/$2/ig;
		print STDERR "Found film '$save'\n";
		$save =~ s/[:\s]+/_/g;
	}
	$save =~ s/(\.flv)?$/.flv/;
	$save =~ s|/|_of_|g;
	$save =~ s/[\*\?\'\"]//g;	# Get rid of troublesome characters.
	# ffmpeg gets confused easily

	# Get video
	#print "TITLE; $title -> $save\n";
	my $video = $YOUTUBE.$film."&t=$and_t";
	debug("Video: $video");
	print "Saving to: $save\n";
	system("$GET_URL \Q$video\E > \Q$save\E");

	# Attempt convert to .mov
	my $mov = $save;
	$mov =~ s/\.flv$/.mov/;
	print "Convert to: $mov\n";
	exec($FFMPEG,"-v",0,"-i",$save,$mov) unless fork;
	if ($opt->{bg}) {
		sleep 1;	# To let the intial ffmpeg output go through..
	} else {
		wait;
	}
}

##################################################
# Main code
##################################################
sub main {
	my $opt = parse_args();

	if ($opt->{dom} =~ /youtube/i) {
		$opt->{film} = "watch?v=$opt->{film}"
			if $opt->{url} =~ s|www.youtube.com/v/|www.youtube.com/watch?v=|;
		usage("Couldn't find youtube video (URL must contain 'v=[video_id]')")
			unless $opt->{film} =~ /v=([a-z0-9_-]+)/i;
		return youtube($opt, $1);
	}

	if ($opt->{dom} =~ /ifilm/i) {
		usage("Couldn't find iFilm video (URL must contain a number/film id)")
			unless $opt->{film} =~ /([0-9]+)/;
		return iFilm($opt, $1);
	}
}
main();
...although it's still not very streamlined...what I'd like is to get this clever javascript bookmark to work in the browser. Why doesn't that script work even with javascript enabled in the preferences?

Last edited by gogol; 2007-08-14 at 19:52.