最近我在弄一个在线转换视频格式(开源的Flash播放器,flv格式的视频文件)的例子,工具还是老工具mencoderffmpeg,在线转换的部分参照网上的例子我又加以修改做好了,就是有几个地方不知道如何判断状态:
1.用Struts做的上传(代码在下一贴跟上),上传视频文件(常规的rm、rmvb、wmv之类的)的时候怎样加一个进度条?上传完以后怎样知道视频文件上传完了,然后调用转码的方法?
2.转码完毕后.怎样知道转码完毕?
视频文件在上传和转码(生成flv格式)的时候文件的大小都是不断增大的,根据什么判断文件上传和转码完毕?

解决方案 »

  1.   

    UploadAction.javapackage tdy218.fileupload;import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import org.apache.struts.action.*;
    import org.apache.struts.upload.FormFile;
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.TimeZone;
    import java.text.SimpleDateFormat;
    import tdy218.fileupload.*;public class UploadAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception 
    {
     String target = "success",uploadtime = "",addtime = "";
     LeafForm leafForm = (LeafForm)form;
     Leaf leaf = new Leaf();
          leaf.setTitle(leafForm.getTitle());
      FormFile pictureFile = leafForm.getPicture();
      int fileSize = pictureFile.getFileSize();

    if((pictureFile!=null)&&(!pictureFile.equals(""))&&(fileSize>0)&&(fileSize<=1024*1024))
    {
    try{
    String path = servlet.getServletContext().getRealPath("/pictures");

        if (!path.endsWith("/")){path = path.concat("/");}
        
    String oldFileName = pictureFile.getFileName();

    TimeZone.setDefault(TimeZone.getTimeZone("GMT+8:00"));
            Date date = new Date();
            SimpleDateFormat bar = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat bare = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                    uploadtime = bar.format(date);
                    addtime = bare.format(date);

            String  newFileName = uploadtime+"&"+oldFileName;
    List<String> list = new ArrayList<String>();
                    list.add(".jpg");
                    list.add(".jpeg");
                    list.add(".gif");
                    list.add(".bmp");
                    String extname = oldFileName.substring(oldFileName.lastIndexOf(".")).toLowerCase();
    if(list.contains(extname))
            {
             InputStream in = pictureFile.getInputStream();
     FileOutputStream out = new FileOutputStream(path+newFileName);
             int c = 0;
     while((c=in.read()) != -1){out.write(c);}
             leaf.setPicture(newFileName);
     leaf.setUploadTime(addtime);
     new LeafDAO().insertLeaf(leaf);
             request.setAttribute("leaf",leaf);
               in.close();
       out.close();
     }
     else
     {
      target = "failure";
     }

       }
       catch(Exception e){e.printStackTrace();}
      }
      else
      {
        target = "failure";
      }

    return mapping.findForward(target);
    }

    }
    文件上传、转码都不算难?就是文件的状态实在难把握。
      

  2.   

    转码的时候在服务端的任务管理器中有一个mencoder或者ffmpeg的进程,转码完毕,对应进程自动结束。但是用Java又是如何监控到操作系统中正在运行的进程那?我现在的思路是这样的:
    1.if(视频文件上传完毕)
     {
      页面跳转到Flash播放器的页面,并在播放器中设置一张图片提示用户:"正在转码和审核中,请耐心等待..."
      convert("xxx.wmv");
     }
     if(转码完毕)
     {
      播放器中还是设置一张图片提示用户:"正在转码和审核中,请耐心等待..."
      人工审核完毕,更改视频文件记录状态(可以在向表中插入记录的时候整一个状态Wait,enum类型的字段,审核完毕后,更改这个状态即可)。
     }关键就是这两个状态的监控、判断。大家帮忙看看。
      

  3.   

    监控Windows操作系统进程的方法我已经找到了。
    还是不知道如何在程序中判断视频文件上传完毕、转码完毕(因为有可能第一个用户使用mencoder或者ffmpeg另一个用户也在用,不能用查看系统进程列表里有没有mencoder或者ffmpeg的方法来说明转码完毕)。
    还有一种大胆的想法:修改Tomcat里的startup.bat这个批处理文件,因为这个文件需要一直处于启动状态,把 定时备份MySQL数据库的程序也加到里面,这是其一,还有就是把文件上传和转码这两个过程分开,把转码也写个应用程序,也加载到Tomcat的startup.bat这个批处理文件里,随时监控着指定的文件夹,一旦发现有新文件上传到服务器上,就开一个mencoder或者ffmpeg的进程,然后跟踪这个进程,进程结束,更新对应记录的表。应该很难实现。期待高手指点!~
      

  4.   

    一定一定,呵呵!
    视频转码后的清晰度已经弄得不错了。
    现在我改变思路了:
    集中精力解决上传状态的控制,Apache-commons-FileUpload文件上传组件就有上传进度监控的方法,如果可以在上传完调用转码的方法,就可以了,至少不是几百MB的视频文件就好(我测试过,文件大了,转码速度相当的慢,可以限定大小,超过200MB的视频文件和电视剧、电影列在一起,另外设一个网页处理这种体积大的视频,当然可以让用户多等一会儿)。后台管理员就可以只管视频审核的工作了,视频没转码完,管理员也不可以观看,直到转码完,后台管理员修改该视频文件在数据库中的记录,这样在客户端就应该看到:
    1.视频正在转码和审核中,请耐心等待...
    2.if(一切正常)
      display();
      else
      show("对不起,你所上传的文件转码失败!我们已经记录了该异常,并在后台人工处理,处理期间请查看本站支持的视频文件格式,");
    所以现在我觉得我们应该把精力放在文件上传的进度条上,希望能访Ajax实现,不用Struts也可以,用例子的朋友请共享一下,我做好后也会把我的贴出来。网上有DWR+Ajax+Struts+Commons-FileUpload.jar实现的例子,我没学过DWR,看了半天很麻烦,希望大家能有等简单的办法。
    Thanks!
      

  5.   

    这个东西做了好多天了,中间有事耽误了,我不爱半途而废,做半拉子工程,所以打算做完。不管有多难,花多长时间,做一件事情就要做好、做完,哪怕是一个坏结果。目前的进度:
       文件上传(使用Apache-Commons-FileUpload组件+Ajax+JS)已做好;
       在线转码(支持常见的RM、RMVB、WMV、AVI、3GP、MP4、MPG/MPEG、MOV、ASF,写在这里的几种格式均已测试过,清晰度与原始视频文件不相上下,有些转换后FLV文件的清晰度不亚于土豆网-黑豆高清版 版块内的视频,这要取决于原始视频文件的清晰度);
       然后就该说说视频状态的判断了,我在建表时候,设置了一个字段,专门来判断视频的状态的。CREATE TABLE `videoinfo` 
    (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `name` varchar(45) DEFAULT NULL,      //视频名称
     `path` varchar(90) DEFAULT NULL,      //转换成FLV格式的视频文件存贮的相对路径,如flvs/Dream Long.flv
     `context` text,                       //视频简介
     `pubman` varchar(45) DEFAULT NULL,    //发布人
     `regdate` varchar(60) DEFAULT NULL,   //发布日期
     `status` enum('-2','-1','0','1') DEFAULT '-1',  //-2表示视频未通过审核,-1表示正在转码和审核中,
                                                     //0表示转码完毕等待审核,1表示转码和审核完毕可以播放。
     `passreason` text,                     未通过审核的理由
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=gbk;总的来看,用到的知识点有:  文件上传:Ajax+prototype.js+Apache-Commons-FileUpload1.21.jar+Tab菜单+模态对话框(用DIV仿)+JS
      运行环境:Win32+Tomcat6.0+MySQL5.1+JDK&JRE1.6
      所用工具:ffmpeg+flashplayer+mencoder
      后台:Struts+DAO  //这也是我比较擅长的写法。现在遇到的问题:
       就是如何解决FLV文件的状态,到底是转码中还是已经转码成功。关于这一点,我是这样想的:
       实例化DAO的一个对象时,读取一下FLV文件的大小,隔两秒钟以后再读取一下同一个FLV文件的大小(转码中的文件是不断增大的),拿后面得出的数值减去第一次读取得到的数值,如果之差等于0,表示转码完毕,更新该视频的状态码,由默认的-1变成0(数据库中的那个状态字段的值),如果之差不等于0,表明正在转码中,不更改视频状态状态。在前台,根据-2、-1、0、1 这几个状态码判断并显示视频文件当前的状态。可我这样想的也不好实现。
    这个帖子我打算再等等再结,期待大家的好想法。最后我会把转码的那个文件源码、转码状态判断整理后贴出来,希望对大家有用。     
      

  6.   

    即将结贴,处理转码中的文件的大小的思路还采用:
    读取一下FLV文件的大小,隔两秒钟以后再读取一下同一个FLV文件的大小(转码中的文件是不断增大的),拿后面得出的数值减去第一次读取得到的数值,如果之差等于0,表示转码完毕,更新该视频的状态码,由默认的-1变成0(数据库中的那个状态字段的值),如果之差不等于0,表明正在转码中,不更改视频状态状态。response.setHeader("Refresh","2;URL=handle.jsp");  //2秒后跳转到制定的URL地址。配合Java定时器java.util.Timer 每隔1.5*1000=1000ms调用读取FLV文件的大小的方法。根据实际情况改改应该就可以了。
      

  7.   

    做到最后了,判断转码状态的那一部分做的不是太好,希望大家帮忙看看,出出主意!转码中的文件状态判断:public ActionForward show(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws Exception                        
        {
          String id = request.getParameter("id");
          String target = "show";
          Connection con = null;
          PreparedStatement ps = null;
          try
          {
           VideoActionForm row = new VideoDAO().show(id);  //返回一个video对象。
           String  video_path = request.getSession().getServletContext().getRealPath("\\").concat(row.getVpath().replaceAll("/","\\\\"));
           File video_file_first = new File(video_path);
           if(video_file_first.exists())
           {
             int first_read_size = (int)video_file_first.length(); //第一次读取文件大小.
             try
             {
              con = new DBConnection().getConnection();  //利用连接数据库,延长两次读取文件大小的时间。
             }   
             catch(Exception e)
             {
              System.out.println(e.getMessage());
             }
             File video_file_last = new File(video_path); 
             
             int last_read_size = (int)video_file_last.length(); //第二次读取文件大小.
             
             if((last_read_size-first_read_size)==0) //如果电脑当前CPU比较高的话,转换中的视频文件的状态码之差也是0,正常情况下如果CPU不高,转换中的视频文件的状态码之差不会为0.
             {
               String sql = "update videoinfo  set status=? where id=?";
               ps = con.prepareStatement(sql);
               ps.setString(1,"0"); //0表示转码完毕的状态。
                ps.setString(2,id);
               ps.execute();
               
               if(con != null)
                 {
                 try{
                     con.close();
                     new DBConnection().closeCon();
                    }
                 catch(Exception e)
                    {System.out.println(e.getMessage());}
                }
             }
           }
           request.getSession().setAttribute("video",row);
          }
          catch(Exception e)
          {
           System.out.println(e.getMessage());
          }
          return mapping.findForward(target);
        } 
      

  8.   

    终于做好了,历经了这么多天。上面的那个问题不算严重,因为在CPU+内存的占用情况正常情况下,两次读取转码中的视频的值就不一样,当然之差也不为0了,转码完毕的视频两次读取之差就等于0.下午由于开的东西太多了(虚拟机+Tomcat+Q+千千静听+N多个网页+...),所以导致前后两次读取转码中的视频的大小的差也为0了,刚刚找了一个比较大的视频文件测试了一下,正常了(现在就开个Tomcat+Q+...)。
    另外这两种转码工具对CPU的主频是有要求的,我的CPU是:AMD 2800+ 1.99GHZ(机器了),所以转码速率小。
    现在可以处理中文命名的视频文件了,我改成以时间为视频的前缀了.
    由于项目压缩后太大了(58.3 MB),CSDN的下载区上传不上,原来的空间也打不开了,想要参考的朋友留下E-mail,我在有空的时候会发给你。
    另外我使用的这个文件上传(带进度条的例子)页面返回的都是英文的,希望大家能帮忙解决一下(可以在本贴继续留言,可以到我空间留言),谢谢!~刚刚又看了一边说明文档,以前对视频标准不了解,现在知道了,该FLV(FlashPlayer)播放器支持H.264视频标准的,因为他依赖于 Flash Player插件的。
    True fullscreen only works if you have the Flash Player 9,0,28,0 or higher installed. H264 videos only from version 9.0.98. If you use the SWFObject javascript to embed your player, you can activate the auto-update functionality. And don’t forget to set the allowfullscreen set to true in your embed code! 
    //就是加了这一句:s1.addParam("allowfullscreen","true");
      

  9.   

    您的邮件已发送。附件:video.rar(58.30M,剩余5天13小时),还有这么长时间,要的赶快说。  
      

  10.   

    楼主给我也发一份吧   先谢了哈
       [email protected]
      

  11.   

    上传的时候要进度条,可以用swf upload 
    别的问题回答不了。
      

  12.   

    邮件已发送,swf upload我见过,就是在jsp中不会用,楼上这位兄弟要是有在jsp中应用的例子,借我看下。 
      

  13.   

    我正好也在做这个,但找不到怎么下手,希望发给我学习学习
    EMAL:[email protected]   谢谢先了
      

  14.   

    希望发给我学习学习 
    EMAL:[email protected]  谢谢
      

  15.   

    [email protected]
    或者 
    [email protected]
    谢谢!!!分享是真理,更是力量!
      

  16.   

    [email protected]  谢谢!!
      

  17.   

    [email protected]
    能不能发份给我,谢谢了
      

  18.   

    [email protected]
    楼主发我一份,还有 那个进度条到底怎么做啊
    能不能指点一二啊  多谢咯
      

  19.   

    [email protected]
    期待楼主发我一份,谢谢喽
      

  20.   

    [email protected]希望楼主也给俺一份,将十分感谢
      

  21.   

    楼主能不能也发一份给我学习下?
    [email protected]
      

  22.   

    很期待很收到你的回复,大家一起进步,谢谢
    [email protected]
      

  23.   

    给我也发一份吧,我正做这个东西呢,也遇到了问题![email protected]
      

  24.   

    [email protected]也给我发份,非常感谢。。最近正好在弄这个东西
      

  25.   

    楼主可以发我一份吗,烦这个转码已经崩溃了,[email protected] 谢谢
      

  26.   

    找了很久了,[email protected],谢谢啦
      

  27.   

    [email protected]
     期待中 谢谢楼主  
      

  28.   

    [email protected]
    楼主也发我一份吧,极其感谢