Flex 3 Cookbook: Chapter 8, Images, Bitmaps, Videos, Sounds
Pages: 1, 2, 3, 4, 5, 6, 7, 8
Using the mx.controls.VideoDisplay simplifies working
with a cue point object quite substantially. When using the CuePointEvent dispatched by the CuePointManager, unlike in the preceding
case, the received event possesses only three properties: cuePointTime, cuePointName, and cuePointType. If you need more or different
information from the cue point, you can write a custom class to return
the cue point data and set it to the cuePointManager property of the VideoDisplay object. The complete code
listing is shown here:
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.events.CuePointEvent;
private function onCuePoint(event:CuePointEvent):void {
trace(event.cuePointName+" "+event.cuePointTime+"
"+event.cuePointType+" ");
}
]]>
</mx:Script>
<mx:VideoDisplay id="vid" cuePoint="onCuePoint(event)"/>
</mx:VBox>
You need to create a control that a user can use to scrub through a video as it plays.
Create a draggable Sprite
object and listen for any DragEvent events dispatched from it. In the
event handler for the DragEvent,
set the amount to seek forward or backward in the NetStream that is streaming the video to the
Video object.
You can use any draggable display object to set the new position
at which the video should be played. In this example, the seek method of the NetStream begins playback from the specified
point in seconds from the beginning of the video:
ns.seek((playhead.x/timeline.width) * length);
To determine which second in the video that the user meant to
seek, divide the position of the dragged Sprite by the width of the timeline area and
multiply by the length of the video. The NetStream will take care of locating the
appropriate frames in the video and restarting the streaming from that
point.
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import mx.core.UIComponent;
public class Scrubber extends UIComponent
{
private var playhead:Sprite;
private var timeline:Sprite;
private var ns:NetStream;
private var nc:NetConnection;
private var obj:Object = {};
private var length:int;
private var vid:Video;
public function Scrubber () {
super();
playhead = new Sprite();
addChild(playhead);
playhead.graphics.beginFill(0x0000ff, 1);
playhead.graphics.drawCircle(0, 0, 5);
playhead.graphics.endFill();
playhead.addEventListener(MouseEvent.MOUSE_DOWN, startSeek);
timeline = new Sprite();
timeline.graphics.beginFill(0xcccccc, 1);
timeline.graphics.drawRect(0, 0, 200, 10);
timeline.graphics.endFill();
addChild(timeline);
timeline.addChild(playhead);
playhead.y = 4;
vid = new Video();
addChild(vid);
vid.y = 100;
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.connect(null);
}
private function netStatus(event:NetStatusEvent):void {
obj.onMetaData = onMetaData;
ns = new NetStream(nc);
ns.client = obj;
vid.attachNetStream(ns);
ns.play("http://localhost:3001/test.flv");
}
private function onMetaData(obj:Object):void {
length = obj.duration;
trace(length);
}
private function startSeek(mouseEvent:MouseEvent):void {
playhead.startDrag(false, timeline.getBounds(this));
addEventListener(MouseEvent.MOUSE_MOVE, seek);
playhead.addEventListener(MouseEvent.ROLL_OUT, endSeek);
playhead.addEventListener(MouseEvent.MOUSE_UP, endSeek);
}
private function seek(mouseEvent:MouseEvent):void {
ns.seek((playhead.x/timeline.width) * length);
}
private function endSeek(mouseEvent:MouseEvent):void {
removeEventListener(MouseEvent.MOUSE_MOVE, seek);
playhead.stopDrag();
}
This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.
You want to read ID3 data from an MP3 file.
Use the Event.ID3 method
that the Sound class
will dispatch when the ID3 data has been parsed.
The Sound class dispatches an
event when the ID3 data has been parsed from a loaded MP3 file. That
data is then stored as an ID3Info
object, which defines variables to access all the properties written
into the initial bytes of the MP3:
private var sound:Sound;
public function _8_16()
{
sound = new Sound();
sound.addEventListener(Event.ID3, onID3InfoReceived);
sound.load(new URLRequest("../assets/1.mp3"));
}
private function onID3InfoReceived(event:Event):void
{
var id3:ID3Info = event.target.id3;
for (var propName:String in id3)
{
trace(propName + " = " + id3[propName]);
}
}
The information from a song I was listening to while I wrote this recipe appears like this:
TCON = Alternative & Punk TIT2 = The Pink Batman TRCK = 2/9 TPE1 = Dan Deacon TALB = Spiderman Of The Rings TCOM = Dan Deacon
The ID3 info of an MP3 file is simply a grouping of bytes in a certain order that are read and turned into strings or integers. MP3 is the only file format that the Flash Player supports out of the box. Developer Benjamin Dobler of RichApps (www.richapps.de), however, has done some exceptional work with the WAV format. Getting the WAV file to play back in the Flash Player is slightly more tricky. If you're interested, go to Benjamin's site and take a look. If you want to parse the data from a WAV file, it looks like this:
public var bytes:ByteArray;
public var chunkId:String;
public var chunkSize:int;
public var chunkFormat:String;
public var subchunk1Id:String;
public var subchunk1Size;
public var audioFormat;
public var channels;
public var sampleRate;
public var bytesPersecond;
public var blockAlign;
public var bitsPerSample;
public var dataChunkSignature:String;
public var dataChunkLength;
public function read(bytes:ByteArray):void{
this.bytes = bytes;
// Read Header
bytes.endian = "littleEndian";
chunkId = bytes.readMultiByte(4,"utf"); //RIFF
chunkSize = bytes.readUnsignedInt();
chunkFormat = bytes.readMultiByte(4,"utf"); //WAVE
subchunk1Id = bytes.readMultiByte(4,"iso-8859-1"); // 12 Header Signature
subchunk1Size = bytes.readInt(); // 16 4 <fmt length>
audioFormat = bytes.readShort(); // 20 2 <format tag> sample
channels = bytes.readShort(); // 22 2 <channels> 1 = mono, 2 = stereo
sampleRate = bytes.readUnsignedInt();// 24 4 <sample rate>
bytesPersecond = bytes.readUnsignedInt(); //28 4 <bytes/second> Sample-Rate *
Block-Align
blockAlign = bytes.readShort(); // 32 2 <block align> channel * bits/sample / 8
bitsPerSample = bytes.readUnsignedShort(); //34 2 <bits/sample> 8, 16 or 24
dataChunkSignature = bytes.readMultiByte(4,"iso-8859-1"); //RIFF
dataChunkLength = bytes.readInt();
}
If you want to read the header info from an AU file, it would look like this:
public var bytes:ByteArray;
public var magicId;
public var header;
public var datasize;
public var channels;
public var comment;
public var sampleRate;
public var encodingInfo;
public function read(bytes:ByteArray):void{
this.bytes = bytes;
// Read Header
bytes.endian = "bigEndian";
magicId = bytes.readUnsignedInt();
header = bytes.readInt();
datasize = bytes.readUnsignedInt();
encodingInfo = bytes.readUnsignedInt();
sampleRate = bytes.readUnsignedInt();
channels = bytes.readInt();
comment = bytes.readMultiByte(uint(header)-24, "utf");
}
MP3 files may be the easiest format from which to read data, but they are certainly not the only format from which you can read.
You want to display custom animation while an image loads.
Create a custom graphic and listen for the ProgressEvent.PROGRESS event from the Image object
loading the image. Then draw into the graphic by using the bytesLoaded and bytesTotal properties.