The old (but still the current) version of the Adobe Flash plugin (10.2) would simply save all Flash videos (.flv files) in /tmp with names like "/tmp/Flash########" where the #'s are random numbers and letters. You could simply buffer a video on YouTube or any other video hosting site, then go to /tmp in your file browser and copy these files somewhere else. They typically get deleted when Flash exits.
The new version of the flash plugin (10.3) tries to be a little more clever. It still creates the files under /tmp, but then it deletes them immediately while still keeping them open. In Linux, if an opened file is deleted, the OS postpones deletion of the file until the process using it lets it go. So the file can't be seen when you look in /tmp, but the flash plugin can still use it until it's done with it.
So how do you get the FLV files from it now?
1) Get the process ID of the flash plugin
$ ps aux | grep flash kirsle 3324 3.3 1.5 281488 44716 ? Sl 12:01 10:41 /usr/lib/xulrunner-2/plugin-container /home/kirsle/.mozilla/plugins/libflashplayer.so -grebase /usr/lib/xulrunner-2 -appbase /usr/lib/firefox-4 3164 true plugin2) Look at the process's open file descriptors in /proc
$ cd /proc/3324/fd3) List the files to find the FLV file (it will be a symbolic link to a "deleted" /tmp/Flash* file)
$ ls -hal | grep Flash lr-x------ 1 kirsle kirsle 64 Apr 5 12:01 17 -> /tmp/FlashXX9ew4CF (deleted)4) Copy it (by ID) somewhere else
$ cp 17 ~/videoname.flvEasy. One could trivially write a shell script that does this automatically too.
This method should work for the foreseeable future, unless Adobe finds some really clever way to stop this, like encrypting video files somehow, or holding them completely in RAM (not likely because some video files can be pretty large). Processes can't hide anything under /proc. :)
More info about /proc.
UPDATE (May 17 2011): I've written a quick Perl script that copies all active Flash videos to your home directory. It doesn't care about the process name; it just loops through all PIDs in /proc, looking for any that owns a "/tmp/Flash*" name, and copies them to $HOME. It works even when you have multiple videos buffered at the same time.
Download it from: sh.kirsle.net/flashget.
This method can also work for Google Chrome (the above was for Firefox/other browsers that use the old Flash plugin system). In Chrome, the Pepper API is used for the Flash plugin instead.
1) Get the PID of the Pepper plugin for Flash
$ ps aux | grep ppapi noah 14152 25.1 1.4 980444 87828 ? Sl 15:37 0:05 /opt/google/chrome/chrome --type=ppapi --channel=13618.24.1890984534 --ppapi-flash-args --lang=en-US2) Get into this PID's file descriptors
*NOTE:* This one requires root access, unlike for the Firefox instructions above.
$ sudo -i # cd /proc/14152/fd # ls -hal [...cut...] 24 -> /home/noah/.config/google-chrome/Default/Pepper Data/Shockwave Flash/.com.google.Chrome.p9GBU8 (deleted)Look for the file descriptor that points to a "deleted" Flash file (in this example, it's file descriptor #24).
3) Copy it somewhere else
# cp 24 ~your_user/24.flv # chown your_user:your_user ~your_user/24.flvSo, the process is similar for doing it for Firefox, except:
ppapi
process instead of the plugin-container
or libflashplayer.so
/root
instead of your main user's home folder).
There are 18 comments on this page. Add yours.
Is there a way to download Youtube Videos from the shell without GUI Maybe one could modify the Java Applet from www.keepvid.com ...
Here's a small shell script that will do this.
#!/bin/bash # # # FILE: save_flash.sh # # USAGE: ./save_flash.sh # # DESCRIPTION: use to save Flash Videos # Will not work properly if displaying flash on more than # tab at a time currently # # OPTIONS: --- # REQUIREMENTS: --- # BUGS: --- # NOTES: --- # AUTHOR: Timm Gleason(timmgleason_at_gmail_dot_com), # COMPANY: # VERSION: 1.0 # CREATED: 05/13/2011 07:16:37 AM PDT # REVISION: --- # PID=$(pidof plugin-container) echo $PID cd /proc/$PID/fd FILE_INODEls -hal | grep /tmp/Flash | awk '{print $9}' x1 while [ $x -gt 0 ] ; do if [ -e "$HOME/saved_flash_$x.flv" ] ; then ((x++)) else cp $FILE_INODE $HOME/saved_flash_$x.flv x0 fi done
Edit by Kirsle: Fixed code formatting
The 4 steps above work if the video is from Vimeo, but not the last 2 if it's from YouTube (cannot locate and copy them).
The cat and the mouse ....
Not working as of May 2012
works fine... less on youtube page..
works on any site, no issues
-using crunchbang linux
Hello Kirsle,
Merry Xmas!!
I did follow the steps in here to try and download the flash video, but couldn't.
Here is what I did when the video was playing and also after the video completed playing.
My operating system is
[root@localhost ~]# uname -a
Linux localhost.localdomain 3.6.2-4.fc17.x86_64 #1 SMP Wed Oct 17 02:43:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
The steps I followed below
[root@localhost proc]# ps -ef | grep -i flash
root 13729 13565 0 16:17 pts/1 00:00:00 grep --color=auto -i flash
[root@localhost proc]# ps -ef | grep -i flash
deepu 13730 1648 43 16:17 ? 00:00:03 /usr/lib64/xulrunner/plugin-container /usr/lib64/flash-plugin/libflashplayer.so -greomni /usr/lib64/xulrunner/omni.ja -appomni /usr/lib64/firefox/omni.ja 1648 true plugin
root 13766 13565 0 16:17 pts/1 00:00:00 grep --color=auto -i flash
[root@localhost kde-deepu]# cd /proc/13730/fd
[root@localhost fd]# ls -lrt
total 0
lrwx------. 1 deepu deepu 64 Dec 23 16:17 9 -> socket:[317254]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 8 -> anon_inode:[eventpoll]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 7 -> pipe:[313137]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 6 -> pipe:[313137]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 5 -> anon_inode:[eventfd]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 4 -> socket:[39675]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 3 -> socket:[313136]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 23 -> socket:[317343]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 22 -> pipe:[319792]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 21 -> pipe:[319792]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 20 -> pipe:[319791]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 2 -> /home/deepu/.xsession-errors
lr-x------. 1 deepu deepu 64 Dec 23 16:17 19 -> anon_inode:inotify
lrwx------. 1 deepu deepu 64 Dec 23 16:17 18 -> socket:[319610]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 17 -> pipe:[319791]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 16 -> socket:[319715]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 15 -> /home/deepu/.mozilla/firefox/fg5l80h5.default/key3.db
lr-x------. 1 deepu deepu 64 Dec 23 16:17 14 -> /home/deepu/.mozilla/firefox/fg5l80h5.default/cert8.db
lrwx------. 1 deepu deepu 64 Dec 23 16:17 13 -> socket:[313139]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 12 -> pipe:[317256]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 11 -> pipe:[317256]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 10 -> socket:[317255]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 1 -> /home/deepu/.xsession-errors
lr-x------. 1 deepu deepu 64 Dec 23 16:17 0 -> pipe:[23895]
[root@localhost fd]# ls -hal | grep -i flash
[root@localhost fd]# ls -lha
total 0
dr-x------. 2 deepu deepu 0 Dec 23 16:17 .
dr-xr-xr-x. 8 deepu deepu 0 Dec 23 16:17 ..
lr-x------. 1 deepu deepu 64 Dec 23 16:17 0 -> pipe:[23895]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 1 -> /home/deepu/.xsession-errors
lrwx------. 1 deepu deepu 64 Dec 23 16:17 10 -> socket:[317255]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 11 -> pipe:[317256]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 12 -> pipe:[317256]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 13 -> socket:[313139]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 14 -> /home/deepu/.mozilla/firefox/fg5l80h5.default/cert8.db
lr-x------. 1 deepu deepu 64 Dec 23 16:17 15 -> /home/deepu/.mozilla/firefox/fg5l80h5.default/key3.db
lrwx------. 1 deepu deepu 64 Dec 23 16:17 16 -> socket:[319715]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 17 -> pipe:[319791]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 18 -> socket:[319610]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 19 -> anon_inode:inotify
lrwx------. 1 deepu deepu 64 Dec 23 16:17 2 -> /home/deepu/.xsession-errors
l-wx------. 1 deepu deepu 64 Dec 23 16:17 20 -> pipe:[319791]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 21 -> pipe:[319792]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 22 -> pipe:[319792]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 23 -> socket:[317343]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 3 -> socket:[313136]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 4 -> socket:[39675]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 5 -> anon_inode:[eventfd]
lr-x------. 1 deepu deepu 64 Dec 23 16:17 6 -> pipe:[313137]
l-wx------. 1 deepu deepu 64 Dec 23 16:17 7 -> pipe:[313137]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 8 -> anon_inode:[eventpoll]
lrwx------. 1 deepu deepu 64 Dec 23 16:17 9 -> socket:[317254]
The script dint find any either :(
Please could you help me here...
Kind Regards Ram
Edit by Kirsle: fixed formatting
this will get everything AFAIK.
#!/bin/bash args=("$@") args=`echo $args | sed 's/[/]$//'` pids=`eval pgrep -f flashplayer` for pid in $pids; do lsoutput=$(lsof -p $pid | grep '/tmp/Flash[^ ]*') IFS=$'\n' for line in $lsoutput; do lsout1=`echo $line | awk '{print "/proc/" $2 "/fd/" $4}' | sed 's/[rwu]$//'` lsout2=`echo $line | awk '{print $9}' | awk -F '/' '{print $3}'` if [ -n "$args" ];then if [ -d $args ]; then echo "Copying $lsout2 to $args/" eval "cp $lsout1 $args/$lsout2.flv" else echo "The directory \"$args\" doesn't exist" break fi else echo "Copying $lsout2" eval "cp $lsout1 $lsout2.flv" fi done done
Edited by Kirsle: made your code prettier :)
My man !
That was a genius hacking. Thanks a lot and my best wishes to you.
Keep walking... keep haking.
Hi! Do you know any method to play/download a video from Youtube without Flash? I'm wondering if you even get to get the video URL without some flash/cookies working, alas.. BR! Tico
Tico:
I think your asking if a standalone player will play youtube videos? Flash video Downloader firefox plugin wukk get the base url of the video, I think. the .flv file it's self. Hope thats close.
MrBiTs: I wish I was that badass of a shell script coder. I have no idea the original author. Kudos to him/her.
This is a python script that accomplishes the same thing, for you ppl who script/like Python.
Later!
#!/usr/bin/perl #Filename: FlashVideoCapture.pl use strict; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; my $LSOF = 'lsof'; my $FIND = 'flash'; # Find flash files my $POST = 'flv'; # Postfix to save to # Where we save files # %f is $FIND # %d is the next available number # %p is .$POST my $DEST = "found%f.%d%p"; ################################################## # 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] Copies deleted flash files currently open in your browser's cache -d Set debug mode -find <str> What to search for [default $FIND] -post <str> Postfix for saving files [default $POST] -dest <str> Or just specify full destination [default $DEST] (see the script for meanings of %f, %d, %p) USAGE exit -1; } sub parseArgs { usage("You need to be on a system that uses /proc") unless -d '/proc'; my $opt = { find => $FIND, post => $POST, dest => $DEST, }; while (my $arg=shift(@ARGV)) { if ($arg =~ /^-h$/) { usage(); } if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; } if ($arg =~ /^-find$/) { $opt->{find} = shift(@ARGV); next; } if ($arg =~ /^-post$/) { $opt->{post} = shift(@ARGV); next; } if ($arg =~ /^-dest$/) { $opt->{dest} = shift(@ARGV); next; } if ($arg =~ /^-/) { usage("Unknown option: $arg"); } usage("Too many files specified [$arg and $opt->{file}]") if $opt->{file}; } usage("You need to specify a destination with -dest") unless $opt->{dest}; usage("You need to specify something to search for with -find") unless $opt->{find}; $opt; } sub debug { return unless $MAIN::DEBUG; foreach my $msg (@_) { print STDERR "[$PROGNAME] $msg\n"; } } ################################################## # Main code ################################################## sub findFiles { my ($opt) = @_; my @found; # 'lsof /' (The '/' just does files, no sockets, and is faster) open(LSOF,"$LSOF /|") || usage("Can't run [$LSOF]"); while (<LSOF>) { next unless /delete/i; next unless /\Q$opt->{find}\E/i; next if /\.adobe/; # Ignore adobe 'flash' db files chomp; # procname pid user fd usage("Found it, can't parse it [$_]") unless /^\S+\s+(\d+)\s+\S+\s+(\d+)/; push(@found, [$1,$2]); } usage("Couldn't find any deleted cached $opt->{find} files") unless @found; @found; } sub procPath { my ($pid,$fd) = @_; my $path = "/proc/$pid"; usage("Couldn't find $path") unless -d $path; $path .= '/fd'; usage("Couldn't find $path") unless -d $path; $path .= "/$fd"; usage("Couldn't read $path") unless -e $path; $path; } sub destPath { my ($opt) = @_; my $p = $opt->{dest}; $p =~ s/%f/\Q$opt->{find}\E/g; $p =~ s/%p/.\Q$opt->{post}\E/g; my $num = 0; my $path; do { $path = $p; $num++; $path =~ s/%d/$num/g; } until ! -f $path; $path; } sub main { my $opt = parseArgs(); my @found = findFiles($opt); foreach my $found ( @found ) { my $src = procPath(@$found); my $dest = destPath($opt); print "$src -> $dest\n"; system("/bin/cp",$src,$dest); } } main();
Edited by Kirsle: made your code prettier :)
Thanks a lot for this, very useful.
It seems this is no more working with flash 11... I can't see any /tmp/Flash* file even when I have found the corresponding processus (plugin-container in my lsof output is cut out to plugin-co). However, the video stops playing when I try accessing a file in /proc/pid/fd/ I think Adobe has restricted flash even more so we cannot more download videos in this way...
@ralph ...that is a perl script, not python. hope you didnt write that.
This is the error that i m getting.. Can't use string ("flash") as a HASH ref while "strict refs" in use at ./FlashVideoCapture.pl line 85, line 1946.
now what to do
sudo apt-get install -y youtube-dl youtube-dl "https://www.youtube.com/watch?v=II3bftjNQTw"
Hi Kirsle, very nice tutorial - Download Any Flash Video in Linux. I keep coming to it everytime I need to keep any flash video. Thanks.
0.0096s
.