View Single Post
gogol's Avatar
Posts: 177 | Thanked: 57 times | Joined on Aug 2007 @ Washington State, USA
#7
I hacked that script some more to get at what I wanted:
Now I can go around bookmarking interesting videos, then drop to the terminal and run the script to download them. It saves them to MyDocs/.videos folder so mplayer picks em right up. It also gives them their proper name. Screenshot below.

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';
#
# Requires that ifilm/youtube's obfuscation doesn't change drastically.
#
# youtube: http://youtube.com/watch?v=[video_id]
#   video at:  http://youtube.com/get_video.php?l=165&video_id=[video_id]&t=[??]
#   Need to find &t=[c0de] in HTML
#
# ifilm:  http://www.ifilm.com/ifilmdetail/2667392
#   -> http://secure.ifilm.com/qt/portal/2667392_300.mov?e=1159050000&h=6c97297693c58d818e86aba0819abf10
#   Update:  Don't know how to look this up with iFilm's new Flash player
#
# Also see: http://javimoya.com/blog/youtube_en.php
##################################################
# CHANGELOG
##################################################
# 2007/8/16
# ----------------
# Haxxed for the 770 by gogol.  Somebody with 
# better perl skillz, please help
# NOTE: The bookmark parsing REQUIRES that myfilm.pl is in your PATH
#
# 1.02  2006/05/13
# ----------------
# + Updated for new youtube obfuscation (&t=[c0de])
#
# 1.01  2006/04/08
# ----------------
# + Released as myfilm
# + Now handles youtube as well as iFilm
#
# 1.00  2005/12/08
# ----------------
# + Released as diFilm
#
##################################################
#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";

#default save dir for youtube
my $defdir = "/home/user/MyDocs/.videos"; #note no trailing slash

##################################################
# 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
  -z		      Scan /home/user/.bookmarks/MyBookmarks.xml for youtube video links.
			It will then download any that don't already exist in ~/MyDocs/.videos
USAGE
	exit -1;
}

sub parse_args {
	my $opt = {};
	while (my $arg=shift(@ARGV)) {
		if ($arg =~ /^-z$/) {$opt->{bmfile} = 1; next;}
		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->{bmfile};
	$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);
}
###################################################
#Bookmark parse
###################################################
sub getbookmarks { 

my $BMARKS = "/home/user/.bookmarks/MyBookmarks.xml";
open BMARKS, "<$BMARKS" or die "Can't open bookmarks!: $!";
while (<BMARKS>) { chomp;
if ($_ =  m|(http://(?:www\.)?youtube\.com/watch\?v=[^"]+)|i){ push @youtube_vids, $1; }
}
print "Found ",($#youtube_vids + 1)," bookmarked videos:\n";
while ($ourcount < ($#youtube_vids+1) ) {
  print "$ourcount : $youtube_vids[$ourcount]\n";
  @args = ("myfilm.pl", $youtube_vids[$ourcount]);
  $ourcount++;
  system(@args) == 0 or die "failed: $?\n";
  }

}


##################################################
# 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");
	$filename = join "/", $defdir, $save;
	print "$filename is filename\n";
	if (-e $filename) { print "File $defdir/$save already exists, skipping.\n"; return; }
	print "Saving to: $defdir/$save\n";
       system("$GET_URL \Q$video\E > $filename");
	


	# 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);
	}
	if (defined $opt->{bmfile}) {&getbookmarks;} 
	

}
main();
This requires Links and Getopt/Std.pm. (Stick it in /usr/share/perl/5.8.3/Getopt/ next to Long.pm)



Now if somebody that has more than a few minutes experience with perl wanted to give a hand, this could be pretty freekin' cool. Thanks to #regex on freenode or I _never_ would have gotten line 155