一次播放16个视频片段,交互式播放(如滚石)

时间:2013-12-08 17:16:17

标签: delphi video directshow dspack

最近,我看到了一个非常好的主意,就是放一个视频片段。这是关于“像滚石”,我们可以在这里看到: http://video.bobdylan.com/desktop.html

如您所见,您可以与之互动,使用向上/向下键更改频道。

我下载了所有16个单独的子剪辑。

现在,挑战在于制作一个程序,一个单独的玩家也可以做同样的事情。

我试图在另一个论坛上得到一些帮助,但现在我陷入了编程阶段。

请看看这里:

编辑: [已删除链接] 它是Videohelp论坛,与此问题具有相同标题的主题]

我写了一个小程序来加载视频并用马赛克显示它们。这是“改变频道”功能的第一步。 我正在使用DSPack组件,它使用DirectShow和Direct9库,使用Delphi 7。

这里,到目前为止我得到了什么:

Mosaic with 12 videos

如图所示,已加载12个视频。

我计划关闭所有其他视频的可见属性,在实现功能“更改频道”时按时间看一个视频,以减轻系统。但是在马赛克布局中,这是不可能的。

解决此步骤后,我将使用热键实现“更改频道”功能。

问题是我对VideoWindow和FilterGraph的Visible和Active属性感到困惑,我没有相应地使用它们。

到目前为止,这是代码:

procedure TFormPlayWin.FormActivate(Sender: TObject);
begin
  BigScreen := true;
  SmallScreen := false;
  VideoWindow01.Width := 1425;
  VideoWindow01.Height := 761;

  VideoWindow01.Visible := true;
  VideoWindow02.Visible := false;
  VideoWindow03.Visible := false;
  VideoWindow04.Visible := false;
  VideoWindow05.Visible := false;
  VideoWindow06.Visible := false;
  VideoWindow07.Visible := false;
  VideoWindow08.Visible := false;
  VideoWindow09.Visible := false;
  VideoWindow10.Visible := false;
  VideoWindow11.Visible := false;
  VideoWindow12.Visible := false;

    if not FilterGraph01.Active then FilterGraph01.Active := true;
    if not FilterGraph02.Active then FilterGraph02.Active := true;
    if not FilterGraph03.Active then FilterGraph03.Active := true;
    if not FilterGraph04.Active then FilterGraph04.Active := true;
{
    if not FilterGraph05.Active then FilterGraph05.Active := true;
    if not FilterGraph06.Active then FilterGraph06.Active := true;
    if not FilterGraph07.Active then FilterGraph07.Active := true;
    if not FilterGraph08.Active then FilterGraph08.Active := true;
    if not FilterGraph09.Active then FilterGraph09.Active := true;
    if not FilterGraph10.Active then FilterGraph10.Active := true;
    if not FilterGraph11.Active then FilterGraph11.Active := true;
    if not FilterGraph12.Active then FilterGraph12.Active := true;
}
    FilterGraph01.ClearGraph;
    FilterGraph02.ClearGraph;
    FilterGraph03.ClearGraph;
    FilterGraph04.ClearGraph;
{
    FilterGraph05.ClearGraph;
    FilterGraph06.ClearGraph;
    FilterGraph07.ClearGraph;
    FilterGraph08.ClearGraph;
    FilterGraph09.ClearGraph;
    FilterGraph10.ClearGraph;
    FilterGraph11.ClearGraph;
    FilterGraph12.ClearGraph;
}
    FilterGraph01.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined01.flv');
    FilterGraph02.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined02.flv');
    FilterGraph03.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined03.flv');
    FilterGraph04.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined04.flv');
{
    FilterGraph05.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined05.flv');
    FilterGraph06.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined06.flv');
    FilterGraph07.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined07.flv');
    FilterGraph08.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined08.flv');
    FilterGraph09.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined09.flv');
    FilterGraph10.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined10.flv');
    FilterGraph11.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined11.flv');
    FilterGraph12.RenderFile('D:\Meus documentos\Downloads\Bob Dylan\Joined12.flv');
}
    VideoWindow01.PopupMenu := PopupMenu;
    SoundLevel.Position := FilterGraph01.Volume;

    FilterGraph01.Play;
    FilterGraph02.Play;
    FilterGraph03.Play;
    FilterGraph04.Play;
{
    FilterGraph05.Play;
    FilterGraph06.Play;
    FilterGraph07.Play;
    FilterGraph08.Play;
    FilterGraph09.Play;
    FilterGraph10.Play;
    FilterGraph11.Play;
    FilterGraph12.Play;

      FilterGraph02.Active := false;
      FilterGraph03.Active := false;
      FilterGraph04.Active := false;
      FilterGraph05.Active := false;
      FilterGraph06.Active := false;
      FilterGraph07.Active := false;
      FilterGraph08.Active := false;
      FilterGraph09.Active := false;
      FilterGraph10.Active := false;
      FilterGraph11.Active := false;
      FilterGraph12.Active := false;

      VideoWindow02.Visible := false;
      VideoWindow03.Visible := false;
      VideoWindow04.Visible := false;
      VideoWindow05.Visible := false;
      VideoWindow06.Visible := false;
      VideoWindow07.Visible := false;
      VideoWindow08.Visible := false;
      VideoWindow09.Visible := false;
      VideoWindow10.Visible := false;
      VideoWindow11.Visible := false;
      VideoWindow12.Visible := false;
}
end;

上面,我试图让第一个Clip覆盖整个区域并保持其他视频不可见。但是事情变坏了,因为我可以看到VideoWindow 2,3和4,而不是大视频VideoWindow1。

我们的想法是使用热键切换大屏幕和小屏幕,以及“更改频道”。

为了保留处理和同步,我想只运行一个音频轨道。如何从DirectShow过滤器中分离出来?我需要它只播放一个音频。如果我只需要其中一个音轨,那么运行所有音轨的好主意。我必须将其他人静音。

说,我有两个问题:

1 - 如何使上述代码更好地同时处理太多视频。

2 - 如何将音频轨道与其他所有视频静音,但第一个视频会保持活跃状态​​。

2 个答案:

答案 0 :(得分:0)

使用OOP似乎是一项很好的任务。但即使没有阵列,你也可以轻松实现。我会告诉你一个想法..

<强>说明/功能

同时12个迷你屏幕(一个有声音) 你想要一个大屏幕(有可能再次为选择新频道改为12)

<强>实现:

1)加载12个视频并打开屏幕1的声音 2)更改活动的miniScreen(更改焦点和活动声音) 3)openBigScreen与选定的电影 4)返回12miniScreens

<强>组件:

无功 ActiveMiniScreen:TScreen;

minScr01 ... minScr12(和你一样的12个屏幕) bigScr(带有aling allClient,visible = false或第二种形式的额外屏幕) backTo12Button(bigScr.onDoubleClick或第二种形式的按钮)

你需要4种方法..

<强> onFormCreate()

加载所有视频并设置为活动状态(启动声音并使其与其他人视觉差异)

ActiveMiniScreen := miniScr1;
miniScr1.loadVideo()
miniScr1.soundOn
miniScr1.BorderColor:= red

miniScr2.loadVideo()
miniScr2.soundOff
miniScr2.BorderColor:= black
      ...
miniScr12.loadVideo()
miniScr12.soundOff
miniScr12.BorderColor:= black

<强> onMinScreenClick() 所有miniSreens共享相同的onMiniScreen1Click方法

ActiveMiniScreen := Tscreen(Sender)
Tscreen(Sender).SoundOn
Tscreen(Sender).BorderColor:= red

<强> onMinDoubleScreenClick()

BigScreen.visible:=true
BigScreen.align:=alClient
BigScreen.loadVideo( ActiveMiniScreen.video )  //load miniScreen active 's video)
BigScreen.soundOn
ActiveMiniScreen.soundOff

onBigScreenDoubleClick()(DoubleClick或onClick)或form2中的按钮

BigScreen.visible:=false
BigScreen.soundOff
ActiveMiniScreen.soundOn

答案 1 :(得分:0)

如果您希望所有视频同步播放 - 因此当您在视频之间切换它们处于相同位置时,将所有视频加载到单个滤镜图中并将它们连接到单个渲染器,例如支持最多16个流的VMR9。通过设置流的z顺序和相关音频渲染器的音量来切换视频。

这里有一些代码可以帮到你。诀窍是使用Capture Graph将视频和音频渲染到特定的渲染器,这样您就可以使用单个视频和多个音频渲染器。

注意:我没有提供任何错误处理,您需要清理已分配的资源。

  GraphBuilder: IGraphBuilder;
  CaptureGraph: ICaptureGraphBuilder2;
  VMR9: IBaseFilter;
  VMRFilterConfig9: IVMRFilterConfig9;
  VMRWindowlessControl9: IVMRWindowlessControl9;
  vw_position: TRect;
  VMRMixerControl9: IVMRMixerControl9;

  // create the fitler graph
  CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, GraphBuilder);
  // create the capture graph
  CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, CaptureGraph);
  CaptureGraph.SetFiltergraph(IGraphBuilder(GraphBuilder));
  // create add the video renderer filter
  CoCreateInstance(CLSID_VideoMixingRenderer9, nil, CLSCTX_INPROC, IID_IBaseFilter, VMR9);
  GraphBuilder.AddFilter(VMR9, 'Renderer');
  // assign renderer to a TPanel
  VMR9.QueryInterface(IID_IVMRFilterConfig9, VMRFilterConfig9);
  VMRFilterConfig9.SetRenderingMode(VMR9Mode_Windowless);
  VMR9.QueryInterface(IID_IVMRWindowlessControl9, VMRWindowlessControl9);
  vw_position.Left := 0;
  vw_position.Top  := 0;
  vw_position.Right  := Panel.width;
  vw_position.Bottom := Panel.height;
  VMRWindowlessControl9.SetVideoPosition(nil, @vw_position);
  VMRWindowlessControl9.SetVideoClippingWindow(Panel.handle);
  // get mixer control
  VMR9.QueryInterface(IID_IVMRMixerControl9, VMRMixerControl9);
  // to control z-order, alpha etc.. see
  // http://msdn.microsoft.com/en-us/library/windows/desktop/dd390457%28v=vs.85%29.aspx


  // encapsluate the following into a class so you can reuse for each video
  SourceFilter: IBaseFilter;
  AudioRenderer: IBaseFilter;
  // create and file source and render video
  GraphBuilder.AddSourceFilter(stringtoolestr(Filename), stringtoolestr(ExtractFileName(Filename)), FileSource);
  CaptureGraph.RenderStream(nil, nil, FileSource, nil, VMR9 as IBaseFilter);
  // create audio renderer and render audio
  CoCreateInstance(StringToGUID('{79376820-07D0-11CF-A24D-0020AFD79767}'), nil, CLSCTX_INPROC, IID_IBaseFilter, AudioRenderer);
  GraphBuilder.AddFilter(AudioRenderer, 'DirectSound Audio Renderer');
  CaptureGraph.RenderStream(nil, nil, FileSource, nil, AudioRenderer);