Skip to content

Latest commit

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Ti.YoutubePlayer

A native Titanium module that enables inline YouTube video playback without forcing the native OS player.

TitaniumLicenseMaintained

screenshot_1screenshot_2

Features

  • ✅ Inline playback (no forced fullscreen)
  • ✅ Configurable autoplay and loop
  • ✅ Mute/unmute control
  • ✅ Video quality control (Youtube is ignoring this for now)
  • ✅ Adjustable playback speed (0.25x - 2x)
  • ✅ Seek to any point in the video
  • ✅ Detailed state and metadata events
  • ✅ No native controls (Optional)
  • ✅ Caption support
  • ✅ Modern async API

📋 Requirements

  • Titanium SDK 13.0.0+

Installation

1. Download the Module

Download the latest version from the releases page.

2. Install the module in your Titanium project

# Copy the compiled module to:
{YOUR_PROJECT}/modules/iphone/

3. Configure tiapp.xml

Add the module to your tiapp.xml:

<modules>
<module>ti.youtubeplayer</module>
</modules>

Permissions (iOS only)

Add microphone permission to tiapp.xml for recording:

<ios>
<plist>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
</plist>
</ios>

Basic Usage

constYouTubePlayer=require('ti.youtubeplayer');constplayer=YouTubePlayer.createPlayerView({videoId: 'dQw4w9WgXcQ',autoplay: true,loop: true,showControls: false,muted: true,preferredQuality: YouTubePlayer.PLAYBACK_QUALITY_HIGH_RESOLUTION,width: Ti.UI.FILL,height: 300,backgroundColor: '#000'});win.add(player);

Complete API

PropertyTypeDefaultDescription
videoIdStringrequiredYouTube video ID
scalingModeStringtrue'SCALING_ASPECT_FIT' or 'SCALING_ASPECT_FILL'
loopBooleantrueLoop playback
showControlsBooleanfalseShow YouTube controls
mutedBooleantrueStart muted
showCaptionsBooleanfalseShow captions
showFullscreenButtonBooleanfalseShow fullscreen button
preferredQualityString'hd1080'Preferred quality ('small', 'medium', 'large', 'hd720', 'hd1080', 'highres')
autoplayBooleantrueStart playback automatically

Note: All standard Ti.UI.View properties also work (width, height, top, left, backgroundColor, etc.)

Constants

Quality

  • PLAYBACK_QUALITY_AUTO
  • PLAYBACK_QUALITY_SMALL
  • PLAYBACK_QUALITY_MEDIUM
  • PLAYBACK_QUALITY_HD720
  • PLAYBACK_QUALITY_HD1080
  • PLAYBACK_QUALITY_HIGH_RESOLUTION

Scaling Aspects

  • SCALING_ASPECT_FILL
  • SCALING_ASPECT_FIT

Methods

play()

Starts video playback.

player.play();

pause()

Pauses video playback.

player.pause();

stop()

Stops video playback completely.

player.stop();

mute()

Mutes the video audio.

player.mute();

unmute()

Unmutes the video audio.

player.unmute();

isMuted()

Returns whether the player is muted.

constmuted=player.isMuted();Ti.API.info('Muted: '+muted);

Returns:Boolean


seek(seconds)

Seeks to a specific point in the video.

// Jump to 30 secondsplayer.seek(30);// Jump to 1 minute 30 secondsplayer.seek(90);

Parameters:

  • seconds (Number): Position in seconds

getDuration(callback)

Gets the total video duration.

player.getDuration(function(e){Ti.API.info('Duration: '+e.duration+' seconds');});

Callback returns:

  • duration (Number): Duration in seconds

getCurrentTime(callback)

Gets the current playback time.

player.getCurrentTime(function(e){Ti.API.info('Current time: '+e.currentTime+' seconds');});

Callback returns:

  • currentTime (Number): Current time in seconds

setPlaybackRate(rate)

Sets the playback speed.

// Normal speedplayer.setPlaybackRate(1.0);// 1.5x fasterplayer.setPlaybackRate(1.5);// 0.5x slowerplayer.setPlaybackRate(0.5);

Parameters:

  • rate (Number): Speed (valid values: 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0)

changeVideo(videoId)

Changes the current video.

player.changeVideo('dQw4w9WgXcQ');

Parameters:

  • videoId (String): New video ID

loadVideo(params)

Loads and plays a new video.

player.loadVideo({videoId: 'dQw4w9WgXcQ',startSeconds: 10// Optional: start at 10 seconds});

Parameters:

  • videoId (String): Video ID
  • startSeconds (Number, optional): Start time in seconds

cueVideo(params)

Loads a video without starting playback.

player.cueVideo({videoId: 'dQw4w9WgXcQ',startSeconds: 10// Optional});

Parameters:

  • videoId (String): Video ID
  • startSeconds (Number, optional): Start time in seconds

reload()

Reloads the current player.

player.reload();

setPlaybackQuality(quality)

Sets playback quality (not guaranteed by YouTube).

player.setPlaybackQuality('hd1080');// orplayer.setPlaybackQuality(player.PLAYBACK_QUALITY_HD1080);

getAvailableQualityLevels(callback)

Gets available qualities for the current video.

player.getAvailableQualityLevels(function(e){Ti.API.info('Available qualities: '+JSON.stringify(e.levels));});

Callback returns:

  • levels (Array): List of available qualities

Events

playerStateChange

Fired when the overall player state changes.

player.addEventListener('playerStateChange',function(e){Ti.API.info('Player state: '+e.playerState);});

Event properties:

  • playerState (String): 'idle', 'ready', 'error'

playbackStateChange

Fired when the playback state changes.

player.addEventListener('playbackStateChange',function(e){Ti.API.info('State: '+e.state);Ti.API.info('Code: '+e.code);Ti.API.info('Is ready: '+e.isFullyReady);});

Event properties:

  • state (String): 'unstarted', 'ended', 'playing', 'paused', 'buffering', 'cued'
  • code (Number): -1 (unstarted), 0 (ended), 1 (playing), 2 (paused), 3 (buffering), 5 (cued)
  • isFullyReady (Boolean): Indicates if the player is completely ready to receive commands

playbackQualityChange

Fired when playback quality changes.

player.addEventListener('playbackQualityChange',function(e){Ti.API.info('Quality: '+e.quality);});

playbackRateChange

Fired when playback speed changes.

player.addEventListener('playbackRateChange',function(e){Ti.API.info('Playback rate: '+e.rate);});

Event properties:

  • rate (Number): Current playback rate

metadataReceived

Fired when video metadata is loaded.

player.addEventListener('metadataReceived',function(e){Ti.API.info('Title: '+e.title);Ti.API.info('Author: '+e.author);Ti.API.info('Video ID: '+e.videoId);});

Event properties:

  • title (String): Video title
  • author (String): Channel name
  • videoId (String): Video ID

muteChanged

Fired when mute state changes.

player.addEventListener('muteChanged',function(e){Ti.API.info('Muted: '+e.muted);});

Event properties:

  • muted (Boolean): true if muted, false if unmuted

error

Fired when an error occurs.

player.addEventListener('error',function(e){Ti.API.error('Error: '+e.message);Ti.API.error('Code: '+e.code);});

Event properties:

  • message (String): Error message
  • code (Number): Error code
  • type (String): Error type
CodeTypeMessage
2invalid_parameterInvalid parameter value (e.g., invalid video ID)
5html5_errorHTML5 player error
8video_removedVideo has been removed or flagged as inappropriate
100not_foundVideo not found, private, or age-restricted
101embedding_disabledOwner doesn't allow embedding
150embedding_disabledSame as 101 (duplicate)
153missing_refererMissing HTTP Referer header or API Client identification

Examples

Example 1: Player with Mute Button

constYouTubePlayer=require('ti.youtubeplayer');constwin=Ti.UI.createWindow({backgroundColor: '#fff'});constplayer=YouTubePlayer.createPlayerView({videoId: 'dQw4w9WgXcQ',autoplay: true,loop: true,muted: true,width: Ti.UI.FILL,height: 300,top: 0});constmuteButton=Ti.UI.createButton({title: '🔇',width: 50,height: 50,right: 10,top: 10,backgroundColor: '#000',opacity: 0.7,borderRadius: 25});muteButton.addEventListener('click',function(){if(player.isMuted()){player.unmute();}else{player.mute();}});player.addEventListener('muteChanged',function(e){muteButton.title=e.muted ? '🔇' : '🔊';});win.add(player);win.add(muteButton);win.open();

Example 2: Video Playlist

constYouTubePlayer=require('ti.youtubeplayer');constvideos=['dQw4w9WgXcQ','kJQP7kiw5Fk','L_jWHffIx5E'];letcurrentIndex=0;constplayer=YouTubePlayer.createPlayerView({videoId: videos[0],autoplay: true,loop: false,width: Ti.UI.FILL,height: 300});player.addEventListener('playbackStateChange',function(e){if(e.state==='ended'){currentIndex=(currentIndex+1)%videos.length;player.changeVideo(videos[currentIndex]);}});win.add(player);

Example 3: Custom Controls

constYouTubePlayer=require('ti.youtubeplayer');constplayer=YouTubePlayer.createPlayerView({videoId: 'dQw4w9WgXcQ',autoplay: false,showControls: false,width: Ti.UI.FILL,height: 300});constcontrolsView=Ti.UI.createView({height: 60,bottom: 0,backgroundColor: 'rgba(0,0,0,0.7)'});constplayButton=Ti.UI.createButton({title: '▶️',left: 10,width: 50});constpauseButton=Ti.UI.createButton({title: '⏸',left: 70,width: 50});constprogressLabel=Ti.UI.createLabel({text: '0:00 / 0:00',right: 10,color: '#fff'});playButton.addEventListener('click',function(){player.play();});pauseButton.addEventListener('click',function(){player.pause();});// Update progress every secondsetInterval(function(){player.getCurrentTime(function(e){player.getDuration(function(d){constcurrent=Math.floor(e.currentTime);consttotal=Math.floor(d.duration);progressLabel.text=formatTime(current)+' / '+formatTime(total);});});},1000);functionformatTime(seconds){constmins=Math.floor(seconds/60);constsecs=seconds%60;returnmins+':'+(secs<10 ? '0' : '')+secs;}controlsView.add(playButton);controlsView.add(pauseButton);controlsView.add(progressLabel);win.add(player);win.add(controlsView);

Example 4: Wait for Player Ready

constYouTubePlayer=require('ti.youtubeplayer');constplayer=YouTubePlayer.createPlayerView({videoId: 'dQw4w9WgXcQ',autoplay: true,muted: true,width: Ti.UI.FILL,height: 300});player.addEventListener('playbackStateChange',function(e){// Wait for player to be fully ready before executing commandsif(e.state==='playing'){Ti.API.info('Player is ready! Safe to call commands now.');// Now it's safe to unmuteplayer.unmute();// Or change speedplayer.setPlaybackRate(1.5);}});win.add(player);

Example 5: Persist Mute State

If you want to persist the mute state between app sessions:

constYouTubePlayer=require('ti.youtubeplayer');// Load saved mute stateconstsavedMuteState=Ti.App.Properties.getBool('my_youtube_muted',true);constplayer=YouTubePlayer.createPlayerView({videoId: 'dQw4w9WgXcQ',muted: savedMuteState,width: Ti.UI.FILL,height: 300});// Save mute state when it changesplayer.addEventListener('muteChanged',function(e){Ti.App.Properties.setBool('my_youtube_muted',e.muted);Ti.API.info('Mute state saved: '+e.muted);});win.add(player);

Video quality is low

YouTube decides quality based on connection. You can suggest a quality:

constplayer=YouTubePlayer.createPlayerView({videoId: 'VIDEO_ID',preferredQuality: 'hd1080'// or 'highres' for 4K});

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

About

A native Titanium module for iOS that enables inline YouTube video playback without forcing the native iOS player. Built with YouTubePlayerKit.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages