Player de vídeo em FLV usando OSMF [Open Source Media Framework] | FlashPedia

leitura do artigo >

23
jun

Player de vídeo em FLV usando OSMF [Open Source Media Framework]

Aprenda a criar um player de vídeo flv em poucos minutos utilizando o recém lançado OSMF (Open Source Media Framework), um conjunto de classes que facilitam o trabalho e monetização de mídia em Flash. Acompanhe.

Comentários (3) Comentários(7) Categorias Action Script3, Classes, HowTo, IDEs e APIs

Olá amigos!

Recentemente a equipe de opensource da Adobe lançou um framework mais do que excelente, trata-se do OSMF Open Source Media Framework, um conjunto de Classes voltados para trabalho e monetização de mídia em flash (filmes, vídeo, áudio, imagens), que facilita e acelera em muito a vida do desenvolvedor, ainda com o destaque de ser otimizado para o também quentíssimo Flash Player 10.1.

“Brinque” (mas não espere demais dele) com o player abaixo:

Vídeo não carregado

Este artigo não tem como base entregar um player 100% funcional e pronto pra ser utilizado ou distribuído mas sim oferecer um caminho para o desenvolvedor ou estudante da plataforma começar a desenvolver seus próprios aplicativos de mídia baseados no OSMF, criando cada vez mais experiências ricas para o internauta ou seu cliente.

Para iniciar, faça o download aqui http://www.opensourcemediaframework.com/ do framework e inclua ele no seu ClassPath.

Desativando configurações específicas do Flash Player 10.1

O OSMF contém, claro, métodos e funções otimizados para Flash Player 10.1 e isso irá disparar alguns erros no seu Flash (ide) quando você estiver testando o filme e não tiver atualizado o Flash Player para a versão atual, então devido a isso iremos desativar uma das configurações do framework, você pode deixar ativado se quiser, mas precisará instalar o Debug Flash Player ( adobe.com/download) 10.1.

Iremos desativar também a opção de LOGGING, mas essas configurações estaremos desativando apenas para acelerar o processo do artigo, você pode ler a documentação e aprender a utilizar caso deseje. Aliás, você que estiver acompanhando este artigo, precisa ler a documentação do OSMF, ele tem muita coisa importate.

No documento que você for utilizar para fazer o seu player, edite em “file > ActionScript Settings > Config Constants”, adicione duas linhas:

Name: CONFIG::FLASH_10_1 Value: false
Name: CONFIG::LOGGING Value: false

Configurações desligadas

Com isso desativamos essas duas configurações específicas, uma pra flash player 10.1 e outra pra logging, que não iremos utilizar.

Como funciona o OSMF

O OSMF funciona encapsulando todos os processos responsáveis por exibir e controlar arquivos de mídia (imagens, vídeo, áudio, swfs), permitindo ao desenvolvedor criar aplicações ricas baseadas em mídia com alto nível de controle, com possibilidade de criação de plugins dos mais variados tipos (grande maioria dos já criados visando monetização de mídia através de google ad words).

O processo utilizado neste player do artigo segue o fluxo padrão e mais simples do OSMF, onde você:

  1. Cria um MediaContainer(org.osmf.containers.MediaContainer)
  2. Cria um VideoElement (org.osmf.elements.VideoElement)
  3. Cria uma URLResource (resource, endereço, url) – (org.osmf.media.URLResource)
  4. Configura o objeto resource no elemento vídeo
  5. Adiciona o elemento vídeo ao container
  6. Configura o MediaPlayer para controlar o elemento de mídia (org.osmf.media.MediaPlayer)
  7. Define o tipo de mídia do MediaPlayer como sendo o elemento vídeo
  8. Controla

Dessa forma, em síntese, temos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package
{
	import flash.display.MovieClip;
	import org.osmf.containers.MediaContainer;
	import org.osmf.elements.VideoElement;
	import org.osmf.media.MediaPlayer;
	import org.osmf.media.URLResource;
 
	/**
	 * OSMF Basic
	 * @author Eder Lima
	 */
	public class BasicPlayer extends MovieClip
	{
		public function BasicPlayer()
		{
			var container:MediaContainer = new MediaContainer();
			var video:VideoElement = new VideoElement();
			var url:URLResource = new URLResource("video.flv");
			video.resource = url;
			container.addMediaElement(video);
			var player:MediaPlayer = new MediaPlayer();
			player.autoPlay = false;
			player.media = video;
			player.play()
		}
	}
 
}

O interessante do MediaContainer é que ele controla automaticamente a proporção do vídeo em caso de resize, matendo o vídeo sempre ajustado caso você altere o tamanho do stage e altere juntamente o container de vídeo, é muito bom.

Vamos criar um player de vídeo que reproduza o vídeo, pause, altere entre mudo e com volume total (1), com barra de progresso, barra de processo de carregamento do vídeo e um tracker, que pode ser arrastado, avançando ou retrocedendo o vídeo de acordo com a sua posição, que altere o tempo com o arraste e por fim que exiba o tempo atual da reprodução e o tempo total. Ufa! (Isso ainda é pouco comparado com o que se pode fazer com o OSMF);

Criando o Player

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
package
{
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	//importando as classes do framework necessárias para um player simples
	//MediaContainer > Um container que se autoajusta ao palco, permitindo o redimensionamento correto do video
	import org.osmf.containers.MediaContainer;
	//VideoElement > Objeto vídeo
	import org.osmf.elements.VideoElement;
	//MediaPlayer > Player de mídia, seleciona o tipo de mídia (vídeo) e controla
	import org.osmf.media.MediaPlayer;
	//URLResource > Objeto que controla a url do arquivo que será reproduzido
	import org.osmf.media.URLResource;
	//TimeEvent > Classe de eventos que determina quando o filme inicia ou termina
	import org.osmf.events.TimeEvent;
	//importando a tweenlite
	import com.greensock.TweenLite;
	import com.greensock.easing.Strong;
	//importando a Classe Rectangle, utilizada no drag
	import flash.geom.Rectangle;
 
	/**
	 * FPOSMFPlayer
	 * FlashPedia Opensource Media Framework Player
	 * @author Eder Lima
	 */
	public class FPOSMFPlayer extends MovieClip
	{
		//criando objetos do player de vídeo
		private var player:MediaPlayer;
		private var video:VideoElement;
		private var url:URLResource;
		private var container:MediaContainer;
		//criando o rectangle para o arraste do tracker
		private var dragRect:Rectangle;
		//boolean para saber se a execução do filme já foi iniciada
		private var started:Boolean = false;
 
		public function FPOSMFPlayer()
		{
			//iniciando o filme
			addEventListener(Event.ADDED_TO_STAGE, initPlayer);
		}
		private function initPlayer(event:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, initPlayer);
			//executando função que configura o player
			configurePlayer();
			//executando função que configura os controles
			configureControls();
		}
 
		private function configurePlayer():void
		{
			/**
			 * configurando a url do vídeo de acordo com o parâmetro passado através do html,
			 * o parâmetro será "video"
			 */
			root.loaderInfo.parameters['video'] != undefined ? url = new URLResource(String(root.loaderInfo.parameters['video'])) : throwError("URL do vídeo não informada");
			//criando o novo objeto VideoElement
			video = new VideoElement();
			//adicionando a url do video como Resource (usando URLResource) ao vídeo
			video.resource = url;
			//video.resource = new URLResource("video.flv");
			//criando um novo MediaPlayer (ele é quem controlará o vídeo exibido)
			player = new MediaPlayer();
			//definindo para não iniciar automaticamente
			player.autoPlay = false;
			//selecionando a mídia a ser trabalhada, no caso o vídeo
			player.media = video;
			//adicionando um evento para quando a execução do filme terminar
			player.addEventListener(TimeEvent.COMPLETE, movieCompleteHandler);
			//criando um novo container
			container = new MediaContainer();
			//configurando os tamanhos
			container.width = stage.stageWidth;
			container.height = stage.stageHeight;
			//adicionando o vídeo ao container
			container.addMediaElement(video);
			//adicionando o container de vídeo ao palco
			addChild(container);
			//colocando o container de vídeo atrás dos controles, que já estão no palco
			setChildIndex(container, 0);
 
		}
		//configurando os controles do player
		private function configureControls():void
		{
			//configurando as escalas das barras
			bar.seekbar.seekbar.scaleX = 0;
			bar.seekbar.loadedbar.scaleX = 0;
			//configurando o rectangle de arraste do tracker]
			dragRect = new Rectangle(0, 4, bar.seekbar.bgbar.width, 0);
			//criando um array com os botões utilizados no player para facilitar algumas funções
			var controls:Array = [bar.btplay, bar.seekbar.bgbar, bar.timeinfo, bar.seekbar.tracker, bar.btvolume];
			//para cada botão
			for each(var item:MovieClip in controls)
			{
				//usa o HandCursor
				item.buttonMode = true;
			}
			//parando o botão play no estado para iniciar
			bar.btplay.gotoAndStop(1);
			bar.btplay.addEventListener(MouseEvent.CLICK, playVideo);
			//configurando o over sobre o tempo
			bar.timeinfo.mouseChildren = false;
			bar.timeinfo.addEventListener(MouseEvent.ROLL_OVER, overTime);
			bar.timeinfo.addEventListener(MouseEvent.ROLL_OUT, outTime);
			//configurando a barra de progresso para clique
			//desativando a barra de load e a barra de progresso
			bar.seekbar.seekbar.mouseEnabled = false;
			bar.seekbar.loadedbar.mouseEnabled = false;
			//configurando o volume simples / alterna entre mudo e normal
			bar.btvolume.gotoAndStop(1);
			bar.btvolume.addEventListener(MouseEvent.CLICK, toggleMute);
		}
		//função que inicia o vídeo caso ainda não tenha tocado e depois pausa
		private function playVideo(event:MouseEvent):void
		{
			if (!started)
			{
				started = true;
				//ativando o clique sobre a barra de fundo
				bar.seekbar.bgbar.addEventListener(MouseEvent.CLICK, seekOnClick);
				//configurando o arraste do tracker
				bar.seekbar.tracker.addEventListener(MouseEvent.MOUSE_DOWN, seekOnDrag);
				//adicionando um evento para informar o progresso do download do vídeo
				//processo separado dos outros justamente para manter o progresso informando mesmo em caso de o vídeo estar parado
				this.addEventListener(Event.ENTER_FRAME, traceLoad);
			}
			//se o player estiver parado toca, senão pausa
			player.playing ? toPause() : toPlay();
		}
		//função que toca o vídeo
		private function toPlay():void
		{
			//toca o vídeo
			player.play();
			//muda o estado do botão play
			bar.btplay.gotoAndStop(2);
			//adiciona os eventos
			addListeners();
		}
		//função que pausa
		private function toPause():void
		{
			//pausa o vídeo
			player.pause();
			//muda o estado do botão play
			bar.btplay.gotoAndStop(1);
		}
		//adicionando listeners para as barras e o tempo
		private function addListeners():void
		{
			this.addEventListener(Event.ENTER_FRAME, trackInfos);
		}
		//removendo listeners para as barra e o tempo
		private function removeListeners():void
		{
			this.removeEventListener(Event.ENTER_FRAME, trackInfos);
		}
		//informando progresso do filme através das barras e da posição do tracker
		private function trackInfos(event:Event):void
		{
			//informando a escala da reprodução
			bar.seekbar.seekbar.scaleX = player.currentTime / player.duration;
			//posicionando o tracker conforme a execução do filme
			bar.seekbar.tracker.x = player.currentTime / player.duration * bar.seekbar.bgbar.width;
			//informando o tempo total
			bar.timeinfo.timer.duration.text = String(addZero(int(player.duration / 60)) +":" + addZero(int(player.duration % 60)));
			//informando o tempo total
			bar.timeinfo.timer.current.text = String(addZero(int(player.currentTime/60)) +":"+addZero(int(player.currentTime%60)));
		}
		//função que informa o progresso do download do vídeo
		private function traceLoad(event:Event):void
		{
			//informando os bytes carregados
			bar.seekbar.loadedbar.scaleX = player.bytesLoaded / player.bytesTotal;
		}
		//função que permite avançar clicando sobre a barra de progresso
		private function seekOnClick(event:MouseEvent):void
		{
			//executando a função que faz o seek do player, somente se a posição do click for menor que a posição da barra
			//que informa o progresso de carregamento do vídeo
			if (event.target.mouseX <= bar.seekbar.loadedbar.scaleX * bar.seekbar.bgbar.width)
			{
				//informa o tempo para qual o filme deve avançar
				this.seekTo(event.target.mouseX / event.target.width * player.duration);
				//se o player estiver parado
				if (!player.playing)
				{
					//volta a reproduzir
					this.toPlay();
				}
			}
		}
		//função que permite arrastar o tracker e saltar para o tempo específico do filme
		private function seekOnDrag(event:MouseEvent):void
		{
			//remove todos os listeners, dessa forma as barras passam a seguir o comando do usuário
			removeListeners();
			//inicia o arraste do tracker, tendo como limites a barra de fundo
			event.target.startDrag(false, dragRect);
			//adiciona os eventos para quando o mouse estiver em movimento
			event.target.addEventListener(MouseEvent.MOUSE_MOVE, onTrackMove);
			//adiciona os eventos para quando soltarmos o clique do mouse ou quando arrastarmos o ponteiro pra fora da área do tracker
			event.target.addEventListener(MouseEvent.MOUSE_OUT, stopTheDrag);
			event.target.addEventListener(MouseEvent.MOUSE_UP, stopTheDrag);
		}
		//executando os eventos durante o arraste do mouse
		private function onTrackMove(event:MouseEvent):void
		{
			//se a posição do tracker for menor que a escala da barra de progresso de carregamento
			if (event.target.x <= bar.seekbar.loadedbar.scaleX * bar.seekbar.bgbar.width)
			{
				//a barra de progresso de execução segue a posição do tracker
				bar.seekbar.seekbar.scaleX = event.target.x / bar.seekbar.bgbar.width;
				//o tempo é alterado para o tempo representado pela posição do tracker
				bar.timeinfo.timer.current.text = String(addZero(int((event.target.x / bar.seekbar.bgbar.width * player.duration) / 60)) +":" + addZero(int((event.target.x / bar.seekbar.bgbar.width * player.duration) % 60)));
			}
			//senão
			else
			{
				//paramos o arraste
				toStopTheDrag();
			}
			//atualizamos o filme depois de cada movimento do mouse (somente para tornar o arraste mais suave mesmo com framerates baixos)
			event.updateAfterEvent();
		}
		//parando o arraste
		//chamamos uma segunda função para reaproveitamento
		private function stopTheDrag(event:MouseEvent):void
		{
			toStopTheDrag();
		}
		//função que para o arraste
		private function toStopTheDrag():void
		{
			//removendo eventos adicionados ao iniciar o arraste
			bar.seekbar.tracker.removeEventListener(MouseEvent.MOUSE_MOVE, onTrackMove);
			bar.seekbar.tracker.removeEventListener(MouseEvent.MOUSE_OUT, stopTheDrag);
			bar.seekbar.tracker.removeEventListener(MouseEvent.MOUSE_UP, stopTheDrag);
			//parando o arraste do tracker
			bar.seekbar.tracker.stopDrag();
			//saltando para o tempo resultante da posição do tracker
			this.seekTo(bar.seekbar.tracker.x / bar.seekbar.bgbar.width * player.duration);
			//alterando o estado do botão play
			!player.playing ? this.toPlay() : void;
		}
		//alterando entre estado mudo e normal
		private function toggleMute(event:MouseEvent):void
		{
			player.volume <= 0 ? unMute() : mute();
		}
		//alterando para mudo
		private function mute():void
		{
			player.volume = 0;
			bar.btvolume.gotoAndStop(2);
		}
		//alterando para normal
		private function unMute():void
		{
			player.volume = 1;
			bar.btvolume.gotoAndStop(1);
		}
		//função executada ao fim da execução do filme (permite reinício a partir da cache, usa seek(0) no framework)
		private function movieCompleteHandler(event:TimeEvent):void
		{
			//alterando o estado do botão play
			bar.btplay.gotoAndStop(1);
		}
		//função que salta para o tempo especificado do filme
		private function seekTo(time:Number):void
		{
			player.seek(time);
		}
		//função com o mouse sobre o tempo
		private function overTime(event:MouseEvent):void
		{
			TweenLite.to(event.target.timer, .3, { y:-12} );
		}
		private function outTime(event:MouseEvent):void
		{
			TweenLite.to(event.target.timer, .3, { y:0} );
		}
		//informado erros (forma simples, jogando erros na tela de debug)
		private function throwError(error:String = ""):void
		{
			throw new Error(error);
		}
		//normalizando o tempo em 00:00
		private function addZero(value:int):String
		{
			//se o valor for menor ou igual a 9 retorna 0x, senão retorna x
			return value <= 9 ? "0" + value : String(value);
		}
	}
 
}

Bom, como disse no começo o player não é nem de longe uma solução final, então fica pra vocês o exercício de mostrar e esconder os controles e manipular o tamanho dos objetos conforme o tamanho do stage. Quem quiser, claro, pode ir além e criar um controle de volume de arraste e etc.

Arquivos fonte para download:

FlashPedia OSMF Player
Baixado 78 vezes
Tamanho
Clique para fazer o download

Dúvidas? Sugestões? Críticas? Fiquem a vontade nos comentários

Enjoy ;)

Postado em 23-06-2010 por Eder Lima
em Action Script3, Classes, HowTo, IDEs e APIs

Share/Save/Bookmark

Comentários

  • Igor Amendola disse:
    em 23 de junho de 2010

    Parabens, Eder!!
    Mais um post de excelente qualidade :)))

  • Leo Cavalcante disse:
    em 23 de junho de 2010

    Ficou tudo muito fácil com esse framework e o Eder mostrou como! Hehe!
    (y)

  • B'uno Monteiro disse:
    em 24 de junho de 2010

    “Dúvidas? Sugestões? Críticas? Fiquem a vontade nos comentários”(SIC)

    Já que você mesmo permite, então lá vai…
    -MUITO BOM!!!!

    ;P

  • Rodrigo - Ne disse:
    em 24 de junho de 2010

    Exemplo bacana dos recursos do OSMF’
    :)

    \o gtz’ Eder

  • Pedro Lins disse:
    em 27 de junho de 2010

    Excelente! Longe de ser um exemplo final, mas é uma mão na roda.
    Vou agendar uma fuçada nisso essa semana.

    Tô acompanhando Eder, continue nos Post’s Hot Hots.

    Obrigado!

  • Tiago disse:
    em 22 de julho de 2010

    Mto bom o Post!!!
    mas..

    Estou tentando implementar o OSMF em um cd que estou fazendo, utilizando o Gaia Framework.
    Quando entro pela primeira vez na página que contém o vídeo, o vídeo roda perfeitamente. Quando saio e depois volto a mesma página de vídeo, acontece o seguinte erro:

    >TypeError: Error #1034: Falha de coerção de tipo: não é possível converter org.osmf.net.rtmpstreaming::RTMPDynamicStreamingNetLoader@24a726a1 em org.osmf.traits.LoaderBase.

    Entender o erro, eu entendo, o problema é como resolvo. Ja tentei de tudo, até comentar a(s) linha(s) do erro, mas não adianta.

    O que pode ser?

    Vlw!!!

  • Eder Lima disse:
    em 22 de julho de 2010

    Ainda não enfrentei esse problema, precisaria ver a parte do código que inicia o player.

    Já tentou fazer o load e unload sem utilizar o gaia? Pois ele armazena os filmes num dictionary pra não precisar carregar novamente, isso pode influir caso vc inicialize o player de vídeo diretamente na função principal de uma document class.

    Outra coisa, está destruindo o objeto do player ou desativando ao remover ele do palco?
    Realmente, não tenho certeza do que pode ser, pois não fiz ainda nada semelhante ao que você está fazendo.

 Escreva um Comentário

Seu nome

E-mail (não será publicado) (obrigatório)

Website

Comente

Spam protection by WP Captcha-Free