关于秋分的谚语:Youtube技术原理

来源:百度文库 编辑:偶看新闻 时间:2024/05/03 03:33:29

Youtube技术原理

简单的说就是:
1. 网页文件允许上传视频文件(这个和上传其他文件一样的)(作者用的是python的架构)
2. 后台调用ffmpeg对上传的视频进行压缩,输出flv格式的文件。这个开源程序win32和linux都有实现,所以可以适应不用的主机环境。
3. 使用flvtools处理flv文件,标记上时长、帧速、关键帧等元数据,这样的flash文件才可以拖放。
4. 使用 ffmpeg 产生flv文件的缩略,和大图像文件的缩略图是一个道理。
5. 使用适当的flv播放器在网页中播放服务器端生成的flv文件

Django 原文:

Video Blogging using Django and Flash(tm) Video (FLV)

I just added Flash-based (FLV) video blogging support to my Django-powered travel portal site, trogger.de. The whole process is surprisingly simple and straightforward and can be done entirely with free (FLOSS) tools.

The video publishing workflow consists of the following parts:

  • A Django model to store our video and associated information
  • An upload form where the user can upload a video
  • Converting the video into a format usable on the Web
  • Extracting additional details
  • Playing the video in the Web browser
  • Making the player a bit friendlier
  • Advanced features

Following this simple workflow, trogger.de allows users to write and submit a blog post. Once that’s submitted, the user can add one (!) video file to it. When later viewing the blog entry, the attached video is shown in the browser.

The Django model

The Django model for storing the video is rather straightforward. In addition to storing the Video (or, rather, a reference to the video file) in a FileField, I’ve added a reference to the blog submission with which the video is related (I use this to look up the video when browsing the blog). Here’s my model, VideoSubmission:

class VideoSubmission(models.Model):videoupload = models.FileField (upload_to=‘videoupload‘)relatedsubmission = models.ForeignKey(Submission, null=True)comment = models.CharField( maxlength=250, blank=True )flvfilename = models.CharField( maxlength=250, blank=True, null=True )

In addition to the video FileField itself, I’ve added a “flvfilename” field to store the name of the converted movie file (see below).

Uploading the video

Video uploading is done using a normal File upload form. In the view for the upload form, we need to add the FormFields for the file upload fields created by Django:

def v_addvideo(request, submissionid):manipulator=VideoSubmission.AddManipulator()form=FormWrapper(manipulator,{},{})params = {‘userAccount‘:request.user,‘form‘:form,}c = Context( request, params)t = loader.get_template(‘video/addvideo.html‘)sub = Submission.objects.get(pk=submissionid)params[‘submission‘] = subreturn HttpResponse( t.render( c ) )

Our addvideo.html is pretty much the simplest upload form imaginable:

Video hochladen:
(Nur AVI und FLV werden akzeptiert)
{{ form.videoupload}} {{ form.videoupload_file }}
Kommentar:

I’ve added the related submission ID as a hidden field, so that this gets submitted back to the upload process and I can create a link between the video and the blog entry.

Converting the video for use in the site

The users are asked to upload AVI videos to the site, but we cannot play AVI videos directly in the browser (at least not in a browser-independent manner). A good way to publish videos for viewing in a browser is using FLV (Flash(tm) Video) format. This is what YouTube, Google Video and a whole host of other sites use. If it’s good enough for them, it’s good enough for me!

Converting to FLV

So, how to convert the AVI video the user uploaded to a usable FLV format? Luckily, the OSS package ffmpeg [2] provides this conversion functionality (plus a wide range of other video conversion features one of which we’ll come to later on). The good thing about ffmpeg is that it is controlled entirely from the command-line and can be run in headless environments — this is vital for using it on an application server. Most other FLV conversion tools were either for Windows or came with some form of Gnome or KDE gui which wouldn’t have worked on my hosted Linux box.

The basic command for converting a video into FLV format is (see [1] in resources):

ffmpeg -i [sourcefile.avi] -acodec mp3 -ar 22050 -ab 32 -f flv -s 320×240 [destfile.flv]

Adding FLV metadata

This command creates a simple FLV format file, containing the video and audio streams. In addition, FLV files need meta-information such as duration, frames, etc. FLV movie players use this information to calculate progress bar sliders and allow the user to fast-forward or reverse through the video. For reasons which I didn’t bother to research, ffmpeg does not add this information. But there is a package which can: flvtool2 (see [3]). Using this tool, we can add FLV meta-information with the following command:

flvtool2 -U [flvfile]

(Warning, Djangoists — flvtool2 is written in Ruby. Please check your religious language preferences at the door and pick them up as you leave. Thank you).

Adding a video thumbnail

Blog entries in trogger.de can include pictures uploaded by the users. One of these pictures is displayed as a small preview when showing the blog posting (e.g. in the blog overview, or in the list of the latest blog submissions). Wouldn’t it be nice if we could also add a thumbnail for a video submission, so that the blog’s reader can get a first idea of what to expect? I think it would. And, again, ffmpeg comes to the rescue.

ffmpeg can extract single frames from a video stream, storing them in still image format. The command for doing this is:


ffmpeg -y -i [videofile] -vframes 1 -ss 00:00:02 -an -vcodec png -f rawvideo -s 320×240 [thumbnailimage.png]

Putting it all together

With these individual steps, it’s EASY to put together a video conversion function which kicks in once a user has uploaded a video file. Since we have the information which video the user uploaded with the form, we convert this video into FLV format, add metadata and create a thumbnail image:

def convertvideo (video):if video is None:return "Kein Video im Upload gefunden"filename = video.videouploadprint "Konvertiere Quelldatei: %s" + filenameif filename is None:return "Video mit unbekanntem Dateinamen"sourcefile = "%s%s" % (settings.MEDIA_ROOT,filename)flvfilename = "%s.flv" % video.idthumbnailfilename = "%svideos/flv/%s.png" % (settings.MEDIA_ROOT, video.id)targetfile = "%svideos/flv/%s" % (settings.MEDIA_ROOT, flvfilename)ffmpeg = "ffmpeg -i %s -acodec mp3 -ar 22050 -ab 32 -f flv -s 320x240 %s" % (sourcefile,  targetfile)grabimage = "ffmpeg -y -i %s -vframes 1 -ss 00:00:02 -an -vcodec png -f rawvideo -s 320x240 %s " % (sourcefile, thumbnailfilename)flvtool = "flvtool2 -U %s" % targetfileprint ("Source : %s" % sourcefile)print ("Target : %s" % targetfile)print ("FFMPEG: %s" % ffmpeg)print ("FLVTOOL: %s" % flvtool)try:ffmpegresult = commands.getoutput(ffmpeg)print "-------------------- FFMPEG ------------------"print ffmpegresult# Check if file exists and is > 0 Bytestry:s = os.stat(targetfile)print sfsize = s.st_sizeif (fsize == 0):print "File is 0 Bytes gross"os.remove(targetfile)return ffmpegresultprint "Dateigroesse ist %i" % fsizeexcept:print sys.exc_info()print "File %s scheint nicht zu existieren" % targetfilereturn ffmpegresultflvresult = commands.getoutput(flvtool)print "-------------------- FLVTOOL ------------------"print flvresultgrab = commands.getoutput(grabimage)print "-------------------- GRAB IMAGE ------------------"print grabexcept:print sys.exc_info()return sys.exc_info[1]video.flvfilename = flvfilenamevideo.save()return None

Things to note

I’m keeping the media diectory for the uploads and the media directory for the converted results separate. This way, I can later on easily clear the upload area if I decide I don’t need the source videos any more (after all, they eat up valuable hosting space), without having to bother about accidentally deleting the converted data. Yes, I’m sometimes stupid in breathtakingly dumb ways. Also I can exclude the source video files from the daily backup.

If something goes wrong with the conversion, I return the output message from the conversion tool and actually display this in the Web page, so the user can see if there was a problem. I’m not too sure this is a good idea, yet. ffmpeg puts pathnames into its output, so the error message is exposing potentially exploitable information about the directory setup of my server. You might want to consider replacing path names before dumping the output message.

The converted video file is created in a subdirectory of the media root and has the VideoSubmission model instance’s ID as a filename (35.flv). This will always be unique, so there’s no need to think about another unique naming scheme. The PNG image thumbnail also has the ID as a filename, but with a PNG extension (duh!).

Playing the video in the Web browser

Now that the video was uploaded and (hopefully) successfully converted, we need to provide a way of viewing it. For this, I use an FLV player component called FlowPlayer, avilable as a SourceForge project [4]. The FlowPlayer SWF is embedded into the page and parameters are provided based on information from the video. In the blog entry view, I look for a related video submission which I pass in the context as “video”. The view template populates the SWF parameters using information from the “video” instance:

{% if video %}

Dein Browser scheint kein Flash-Plugin installiert zu haben

{{video.comment}}

{% endif %}

Note the inconspicuous “splashImageFile=clicktoplay.jpg” hidden in the jumble of FLV parameters. FlowPlayer provides a very simple way of specifying a “splash screen” image which is displayed in place of the video until the user clicks on the Flash player to view the video. I’ve created a trogger-themed splash screen and use this for all embedded video submissions:

The end result

Thew end result is shown in the screenshot. A user-written blog entry, with an attached video which is played in the browser. Not bad for one day’s work, if I say so myself.


Conversion quality and size issues

Quality of the converted FLV videos is pretty good, even at lower resolutions. Of course, YMMV or you may have other expectations. Using the conversion commands shown above, a 2.6MB camera movie was converted into an FLV file of 590kB. Depending on your intended use of the video (full-screen presentation?), and depending on how much bandwidth you want to burn, you may want to fiddle with some quality and compression parameters in ffmpeg.

Housekeeping

It is definitely a good idea to make sure that the FLV files are not actually served by Django, but directly by Apache (or even by another http server altogether). To serve the video files directly from Apache, we can exclude the video location “showvideo” from processing by Django by adding a section to the httpd.conf:

Alias /showvideo/ "/path/to/my/media/root/video/"SetHandler none

Also, we should consider limiting the size of uploads, since we don’t want to drown in uploaded video (and we don’t want to get out-of-memory errors from Django, which holds the entires file upload in memory at least temporarily). As has been pointed out by Malcolm Tredinnick in the django-users group, this can be achieved using the LimitRequestBody directive.

Open Issues

One issue that I haven’t been able to solve is adequate support for more video formats. Windows Media stuff provides so many proprietary formats, codecs, etc., that it’s hard even for a project such as ffmpeg to keep up. As a result, I’ve limited video upload to AVI files, and make it quite clear to the uploader that potentially the video he’s uploading cannot be used, due to format problems. AVI videos captured by my digital camera (such as the diving video in the screenshot) can be converted quite well. As soon as somebody recodes the video, converts it to WMV, there’s trouble (even more so if the video contains any Digital Restrictions Management). There are loads of forum entries in the Net discussing potential solutions. Since they all involved hacking additional (sometimes binary) codes into ffmpeg, I wasn’t adventurous enough to try them.

If anyone can point me at a reliable way of converting (unprotected) WMV files and other video formats into FLV format, I would be very grateful.

I discovered that MPlayer can also be used for such conversions and can also be run in a headless environment; since conversion with ffmpeg worked, I didn’t do any more experiments — maybe someone else can enlighten me as to wether MPlayer would actually be better or cope with more formats?

Also, I’m doing the video conversion in-line with the browser upload. This is OK for shorter videos, where I can make the user wait for a result. For larger video submissions it might be useful to decouple the video processing and do it in a separate thread, updating the blog entry when finished.

Resources

[1] ffmpeg
http://ffmpeg.mplayerhq.hu/

[3] flvtool2
http://rubyforge.org/projects/flvtool2/

[4] FlowPlayer
http://flowplayer.sourceforge.net/

Tags: Django; Python; FLV; video; trogger

P.S. You can check out a blog entry with video submission in my trogger blog at http://www.trogger.de/blog/8/60/mit-mantas-tauchen-vor-machchafushi/fullentry/.