Skip navigation
Currently Being Moderated

Made a free web MP3 player with OSMF

Mar 17, 2010 3:08 PM

I used iTunes as a skin, and it was fairly quick & easy to do, thanks guys!

 

http://blog.leefernandes.com/?p=251

 

iWebTunes.jpg

 
Replies
  • Currently Being Moderated
    Mar 17, 2010 7:08 PM   in reply to cayennecode

    Nice!

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 21, 2010 9:19 PM   in reply to cayennecode

    The Sound class isn't publicly accessible, as so far we've been able to map the specific properties into our more abstract media APIs.  Sound.length should map to MediaPlayer.duration -- if it doesn't, then please file a bug.  (Glancing at the code, it looks like Sound.length is coupled to the download length, which seems like an inappropriate thing for us to do.  Probably a bug.)

     

    Assuming we can get MediaPlayer.duration to map to Sound.length, is there any other reason why you would need access to the Sound object?

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 22, 2010 9:34 AM   in reply to cayennecode

    I'm curious, do you see accurate numbers when using Sound.length?  I changed the code locally to have duration map to Sound.length, but I see Sound.length growing as the file downloads (i.e. it seems to return the length of the currently downloaded portion of the file).  For example, it starts at 0.15, grows incrementally as the file continues its download, then jumps up to 224 when the download finishes.  Is this what you would expect?

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 22, 2010 10:24 AM   in reply to cayennecode

    I'm a bit confused now.  SoundAdapter.estimatedDuration should be identical to MediaPlayer.duration.  Are you seeing cases where the numbers differ?

     

    Looking at the code more closely, it's possible that the numbers would differ due to the removal of the "progress" event listener in AudioTimeTrait.onDownloadProgress.  If you comment out the "soundAdapter.removeEventListener(...)" line in AudioTimeTrait, does MediaPlayer.duration reflect what you'd expect?

     
    |
    Mark as:
  • Currently Being Moderated
    May 26, 2011 8:55 AM   in reply to cayennecode

    Hey Guys,

     

    Wanted to quickly check if this issue was resolved in a later version of OSMF ? I'm using the latest Strobe Media Playback and compiling it against OSMF 1.5.1 and continue to see this issue.

     

    If this issue isn't resolved, is there a workaround specifically for SMP ?

     

     

    Thanks!

     
    |
    Mark as:
  • Currently Being Moderated
    Jun 12, 2011 11:19 PM   in reply to cayennecode

    Some digging around and looking at the OSMF code answered the question for me. For the case of an MP3 file, OSMF doesn't use the traditional netstream/netconnect mechanism, instead it uses the Sound object to download and play the file. By default, the Sound object in flash has issues with determining the length of the mp3 and that cascades up the stack to create issues with the seekbar. I found a couple of work-arounds for this issue,

     

    1) use mp3infoutil - i integrated mp3infoutil into the SoundAdapter class in OSMF, the disadvantage here is that it only works with MP3's that have ID3v1 tags, if the mp3 has an ID3v2 tag, this doesn't work at all. The modified code for SoundAdapter is (you will need to download the mp3infoutil swc and include it as a part of your compile library list)

     

    /*****************************************************

    *  Copyright 2009 Adobe Systems Incorporated.  All Rights Reserved.

    *****************************************************
    *  The contents of this file are subject to the Mozilla Public License
    *  Version 1.1 (the "License"); you may not use this file except in
    *  compliance with the License. You may obtain a copy of the License at
    http://www.mozilla.org/MPL/
    *  
    *  Software distributed under the License is distributed on an "AS IS"
    *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
    *  License for the specific language governing rights and limitations
    *  under the License.
    *  

    *  The Initial Developer of the Original Code is Adobe Systems Incorporated.
    *  Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems
    *  Incorporated. All Rights Reserved.

    *****************************************************/
    package org.osmf.elements.audioClasses
    {
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
        import flash.media.Sound;
        import flash.media.SoundChannel;
        import flash.media.SoundTransform;
       
        import org.osmf.events.MediaError;
        import org.osmf.events.MediaErrorCodes;
        import org.osmf.events.MediaErrorEvent;
        import org.osmf.media.MediaElement;
        import org.osmf.media.URLResource;
       
       
        import com.fastforwardthinker.util.mp3.events.MP3InfoEvent;
        import com.fastforwardthinker.util.mp3.MP3InfoUtil;
       
        [ExcludeClass]
       
        /**
         * Dispatched when playback of the Sound completes.
         *
         * @eventType flash.events.Event.COMPLETE
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="complete", type="flash.events.Event")]
       
        /**
         * Dispatched when download of the Sound completes.
         *
         * @eventType downloadComplete
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="downloadComplete", type="flash.events.Event")]
       
        /**
         * Dispatched periodically as the download of the Sound progresses.
         *
         * @eventType flash.events.ProgressEvent.PROGRESS
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="progress", type="flash.events.ProgressEvent")]
               
        /**
        * @private
        *
        * Utility class to make working with the Sound class a bit easier.
        * 
        *  @langversion 3.0
        *  @playerversion Flash 10
        *  @playerversion AIR 1.5
        *  @productversion OSMF 1.0
        */
        public class SoundAdapter extends EventDispatcher
        {
            public static const DOWNLOAD_COMPLETE:String = "downloadComplete";   
           
            public function SoundAdapter(owner:MediaElement, sound:Sound)
            {
                super();
               
                this.owner = owner;
                trace("sound adapter init and resource is " + (owner.resource as URLResource).url.toString());
                this.sound = sound;
                _soundTransform = new SoundTransform();
               
                sound.addEventListener(Event.COMPLETE, onDownloadComplete, false, 0, true);
                sound.addEventListener(ProgressEvent.PROGRESS, onProgress, false, 0, true);
                sound.addEventListener(IOErrorEvent.IO_ERROR, onIOError, false, 0, true);
                //sound.addEventListener(Event.ID3, id3Handler);
                trace("input into mp3infoutil " + (owner.resource as URLResource).url.toString());
                MP3InfoUtil.getInfo( (owner.resource as URLResource).url.toString() );
                MP3InfoUtil.addEventListener(MP3InfoEvent.COMPLETE, onMP3InfoComplete );
                MP3InfoUtil.addEventListener(MP3InfoEvent.ERROR, onMP3InfoError );
               
            }
           
            public function onMP3InfoComplete(e:MP3InfoEvent):void{
                    //output.text = '';
                    /*trace("*********** mp3 info ********");
                    for( var key:String in e.info ){
                        trace(key + ": " + e.info[key]);
                    }*/
                   
                    var durationFromMp3Info:Number = new Number(e.info["lengthSeconds"]);
                    trace("********** the duration of the file is = " + durationFromMp3Info);  
                   
                    this.customDuration = durationFromMp3Info;
                   
                    dispatchEvent(new Event(DOWNLOAD_COMPLETE));
                }
               
            public function onMP3InfoError(e:MP3InfoEvent):void{
                    trace(e.info.message);
                }
           
            /*public function id3Handler(e:Event):void{
                trace("id3Handler: " + e);
                trace("**************length according to id3 tag is " + e.target.id3.songName);
            }*/
           
            public function get currentTime():Number
            {           
                return channel != null ? channel.position / 1000 : lastStartTime / 1000;
            }

     

            /**
             * Returns an estimate of the duration of the partially downloaded
             * audio file, in seconds.
             * 
             *  @langversion 3.0
             *  @playerversion Flash 10
             *  @playerversion AIR 1.5
             *  @productversion OSMF 1.0
             */
            public function get estimatedDuration():Number
            {
                    /*trace("sound length = " + sound.length);
                    trace("bytesLoaded = " + sound.bytesLoaded);
                    trace("bytesTotal = " + sound.bytesTotal);*/
                    //return sound.length / (1000 * sound.bytesLoaded / sound.bytesTotal);
                    return this.customDuration;           
            }   
           
            /*public function setCustomDuration(customDuration:Number):void{
                this.customDuration = customDuration;
            }*/
           
            public function get soundTransform():SoundTransform
            {
                return _soundTransform;
            }
           
            public function set soundTransform(value:SoundTransform):void
            {
                _soundTransform = value;
                if (channel != null)
                {
                    channel.soundTransform = value;   
                }       
            }

     

            /**
             * Play the sound.  If the given time is -1, starts from the
             * beginning.  Otherwise, attempts to play from that point.
             *
             * @returns True if playing the file was successful, false if
             * playback failed for some reason.
             * 
             *  @langversion 3.0
             *  @playerversion Flash 10
             *  @playerversion AIR 1.5
             *  @productversion OSMF 1.0
             */
            public function play(time:Number=-1):Boolean
            {
                var success:Boolean = false;
               
                if (channel == null)
                {
                    // HTTPS urls can throw errors here.
                    try
                    {
                        channel = sound.play(time != -1 ? time : lastStartTime);
                    }
                    catch (error:ArgumentError)
                    {
                        // Do nothing, just send the playback error (see below).
                        channel = null;                   
                    }
                   
                    if (channel != null)
                    {
                        playing = true;
                       
                        // Apply any previously-set SoundTransform on the new channel.
                        channel.soundTransform = _soundTransform;
                       
                        channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
                       
                        success = true;
                    }
                    else
                    {
                        // When channel is null, we either have no sound card or no
                        // sound channels available.
                        owner.dispatchEvent
                            ( new MediaErrorEvent
                                ( MediaErrorEvent.MEDIA_ERROR
                                , false
                                , false
                                , new MediaError(MediaErrorCodes.SOUND_PLAY_FAILED)
                                )
                            );
                    }
                }
               
                return success;
            }
                       
            public function pause():void
            {
                if (channel != null)
                {
                    lastStartTime = channel.position;
                   
                    clearChannel();
                    playing = false;
                }
            }
           
            public function stop():void
            {
                if (channel != null)
                {
                    lastStartTime = 0;
                   
                    clearChannel();
                    playing = false;
                }
            }
           
            public function seek(time:Number):void
            {
                var wasPlaying:Boolean = playing;
               
                if (channel != null)
                {
                    clearChannel();
                }

     

                play(time*1000);

     

                if (wasPlaying == false)
                {
                    pause();
                }
            }   
                           
            // Internals
            //
           
            private function clearChannel():void
            {
                if (channel != null)
                {
                    channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete);
                    channel.stop();
                    channel = null;
                }
            }
           
            private function onSoundComplete(event:Event):void
            {
                lastStartTime = channel.position;
               
                clearChannel();
                playing = false;
               
                // Signal playback has completed.
                dispatchEvent(new Event(Event.COMPLETE));
            }
                   
            private function onDownloadComplete(event:Event):void
            {
                dispatchEvent(new Event(DOWNLOAD_COMPLETE));
            }
           
            private function onProgress(event:ProgressEvent):void
            {
                dispatchEvent(event.clone());
            }

     

            private function onIOError(event:IOErrorEvent):void
            {
                owner.dispatchEvent
                    ( new MediaErrorEvent
                        ( MediaErrorEvent.MEDIA_ERROR
                        , false
                        , false
                        , new MediaError(MediaErrorCodes.IO_ERROR)
                        )
                    );
            }
           
           
            private var customDuration:Number;
            private var owner:MediaElement;
            private var _soundTransform:SoundTransform;   
            private var sound:Sound;   
            private var playing:Boolean = false;       
            private var channel:SoundChannel;
            private var lastStartTime:Number = 0;
        }
    }

     

     

    2) the second work around is to actuall pass in the duration of the mp3 as a flashvar into the player (not elegant at all, but works!!), you will also need to modify the AudioTrait.as file to add the setCustomDimension() method

     

    /*****************************************************

    *  Copyright 2009 Adobe Systems Incorporated.  All Rights Reserved.

    *****************************************************
    *  The contents of this file are subject to the Mozilla Public License
    *  Version 1.1 (the "License"); you may not use this file except in
    *  compliance with the License. You may obtain a copy of the License at
    http://www.mozilla.org/MPL/
    *  
    *  Software distributed under the License is distributed on an "AS IS"
    *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
    *  License for the specific language governing rights and limitations
    *  under the License.
    *  

    *  The Initial Developer of the Original Code is Adobe Systems Incorporated.
    *  Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems
    *  Incorporated. All Rights Reserved.

    *****************************************************/
    package org.osmf.elements.audioClasses
    {
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
        import flash.media.Sound;
        import flash.media.SoundChannel;
        import flash.media.SoundTransform;
       
        import org.osmf.events.MediaError;
        import org.osmf.events.MediaErrorCodes;
        import org.osmf.events.MediaErrorEvent;
        import org.osmf.media.MediaElement;
       
       
        [ExcludeClass]
       
        /**
         * Dispatched when playback of the Sound completes.
         *
         * @eventType flash.events.Event.COMPLETE
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="complete", type="flash.events.Event")]
       
        /**
         * Dispatched when download of the Sound completes.
         *
         * @eventType downloadComplete
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="downloadComplete", type="flash.events.Event")]
       
        /**
         * Dispatched periodically as the download of the Sound progresses.
         *
         * @eventType flash.events.ProgressEvent.PROGRESS
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion OSMF 1.0
         */
        [Event(name="progress", type="flash.events.ProgressEvent")]
               
        /**
        * @private
        *
        * Utility class to make working with the Sound class a bit easier.
        * 
        *  @langversion 3.0
        *  @playerversion Flash 10
        *  @playerversion AIR 1.5
        *  @productversion OSMF 1.0
        */
        public class SoundAdapter extends EventDispatcher
        {
            public static const DOWNLOAD_COMPLETE:String = "downloadComplete";   
           
            public function SoundAdapter(owner:MediaElement, sound:Sound)
            {
                super();
               
                this.owner = owner;
                this.sound = sound;
                _soundTransform = new SoundTransform();
               
                sound.addEventListener(Event.COMPLETE, onDownloadComplete, false, 0, true);
                sound.addEventListener(ProgressEvent.PROGRESS, onProgress, false, 0, true);
                sound.addEventListener(IOErrorEvent.IO_ERROR, onIOError, false, 0, true);
                //sound.addEventListener(Event.ID3, id3Handler);
            }
           
            /*public function id3Handler(e:Event):void{
                trace("id3Handler: " + e);
                trace("**************length according to id3 tag is " + sound.id3);
            }*/
           
            public function get currentTime():Number
            {           
                return channel != null ? channel.position / 1000 : lastStartTime / 1000;
            }

     

            /**
             * Returns an estimate of the duration of the partially downloaded
             * audio file, in seconds.
             * 
             *  @langversion 3.0
             *  @playerversion Flash 10
             *  @playerversion AIR 1.5
             *  @productversion OSMF 1.0
             */
            public function get estimatedDuration():Number
            {
                    /*trace("sound length = " + sound.length);
                    trace("bytesLoaded = " + sound.bytesLoaded);
                    trace("bytesTotal = " + sound.bytesTotal);*/
                    //return sound.length / (1000 * sound.bytesLoaded / sound.bytesTotal);
                    return this.customDuration;           
            }   
           
            public function setCustomDuration(customDuration:Number):void{
                this.customDuration = customDuration;
            }
           
            public function get soundTransform():SoundTransform
            {
                return _soundTransform;
            }
           
            public function set soundTransform(value:SoundTransform):void
            {
                _soundTransform = value;
                if (channel != null)
                {
                    channel.soundTransform = value;   
                }       
            }

     

            /**
             * Play the sound.  If the given time is -1, starts from the
             * beginning.  Otherwise, attempts to play from that point.
             *
             * @returns True if playing the file was successful, false if
             * playback failed for some reason.
             * 
             *  @langversion 3.0
             *  @playerversion Flash 10
             *  @playerversion AIR 1.5
             *  @productversion OSMF 1.0
             */
            public function play(time:Number=-1):Boolean
            {
                var success:Boolean = false;
               
                if (channel == null)
                {
                    // HTTPS urls can throw errors here.
                    try
                    {
                        channel = sound.play(time != -1 ? time : lastStartTime);
                    }
                    catch (error:ArgumentError)
                    {
                        // Do nothing, just send the playback error (see below).
                        channel = null;                   
                    }
                   
                    if (channel != null)
                    {
                        playing = true;
                       
                        // Apply any previously-set SoundTransform on the new channel.
                        channel.soundTransform = _soundTransform;
                       
                        channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
                       
                        success = true;
                    }
                    else
                    {
                        // When channel is null, we either have no sound card or no
                        // sound channels available.
                        owner.dispatchEvent
                            ( new MediaErrorEvent
                                ( MediaErrorEvent.MEDIA_ERROR
                                , false
                                , false
                                , new MediaError(MediaErrorCodes.SOUND_PLAY_FAILED)
                                )
                            );
                    }
                }
               
                return success;
            }
                       
            public function pause():void
            {
                if (channel != null)
                {
                    lastStartTime = channel.position;
                   
                    clearChannel();
                    playing = false;
                }
            }
           
            public function stop():void
            {
                if (channel != null)
                {
                    lastStartTime = 0;
                   
                    clearChannel();
                    playing = false;
                }
            }
           
            public function seek(time:Number):void
            {
                var wasPlaying:Boolean = playing;
               
                if (channel != null)
                {
                    clearChannel();
                }

     

                play(time*1000);

     

                if (wasPlaying == false)
                {
                    pause();
                }
            }   
                           
            // Internals
            //
           
            private function clearChannel():void
            {
                if (channel != null)
                {
                    channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete);
                    channel.stop();
                    channel = null;
                }
            }
           
            private function onSoundComplete(event:Event):void
            {
                lastStartTime = channel.position;
               
                clearChannel();
                playing = false;
               
                // Signal playback has completed.
                dispatchEvent(new Event(Event.COMPLETE));
            }
                   
            private function onDownloadComplete(event:Event):void
            {
                dispatchEvent(new Event(DOWNLOAD_COMPLETE));
            }
           
            private function onProgress(event:ProgressEvent):void
            {
                dispatchEvent(event.clone());
            }

     

            private function onIOError(event:IOErrorEvent):void
            {
                owner.dispatchEvent
                    ( new MediaErrorEvent
                        ( MediaErrorEvent.MEDIA_ERROR
                        , false
                        , false
                        , new MediaError(MediaErrorCodes.IO_ERROR)
                        )
                    );
            }
           
           
            private var customDuration:Number;
            private var owner:MediaElement;
            private var _soundTransform:SoundTransform;   
            private var sound:Sound;   
            private var playing:Boolean = false;       
            private var channel:SoundChannel;
            private var lastStartTime:Number = 0;
        }
    }

     

     

     

    hope this helps!!!

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points