We have Integrated Bitmovin player in android with casting and ads features. Ad is preroll ad. While casting, Video ad is playing in Mobile and Video content is playing in TV. Let’s say I have video ad of 20 secs, While casting this 20 secs Video ad is playing in mobile and Video content is playing in TV (for 20 secs). After the Video Ad is completed in the mobile, actual video content is started in the mobile and now in TV two audios are coming. One is Audio with Video Content starting from 0 secs and other Audio which is continues from 21 secs. Below is the video attached. Kindly help us in resolving this.
Thanks in advance.
Hi @meworldet.com , this sounds like a bug. Could you maybe create a minimal reproducible sample based on our casting sample to help us reproduce the issue?
Hi @Lukas - This issue is not happening for all the videos. Only for few specific videos, we are seeing this issue. We have implemented the Casting example
but , only for few videos, we are seeing this issue.
It would be great if you could provide one of the failing streams. If you do not want to share it publicly, please send it in a private direct to me.
We have almost the same issue, we don’t have a Custom Receiver for the ads, so we are watching ads on device, but if Chromecast is on, ads will be played on phone/device and Content will be played on TV/Chromecast, and if we pause the ads, Content is paused too and if we resume the ads, Content is resumed too.
We don’t know if player can control ads play/pause “toggle” before content when Chromecast is on.
Hi @gledezma , thanks for sharing your issue. Can you please share following additional information?
- Bitmovin Player Version
- IMA SDK dependency version
- If possible VAST/VMAP Ad URL?
- Bitmovin player configuration including PlaybackConfig and Advertising Configuration?
- Is
isAutoplayEnabled
configuration set to true? - Android version where this issue is reproduced.
In general Bitmovin player takes care of disabling/stopping client side Ads playing on Android device when casting is started/enabled. So this is either a configuration issue or a potential bug. Above information will help us triage this better. If you can also share a sample application where we can reproduce this behaviour, that will be best next step for us investigate.
Here is the information:
- Bitmovin Player Version: 3.23.0
- IMA SDK Version: 3.27.1 / play services ads 18.0.1
- Vast Ad URL: Riivi Vast
- Player Config:
private fun getAdConfig(dataMediaResponse: MediaPlaylist): AdvertisingConfig {
url = getVastUrl(mediaPlaylist = dataMediaResponse)
/*Log.e("URL vast", url)*/
val adSource = AdSource(
AdSourceType.Ima,
url)
val arrayAds = arrayOf(adSource)
val addItem = AdItem(arrayAds, "pre", replaceContentDuration = 0.0, preloadOffset = 1.0)
return AdvertisingConfig(addItem)
}
val adConfig = getAdConfig(dataMediaResponse)
val playerConfig = PlayerConfig(
advertisingConfig = adConfig,
styleConfig = StyleConfig(
isUiEnabled = false,
isHideFirstFrame = true,
),
playbackConfig = PlaybackConfig(
isAutoplayEnabled = true
)
)
//set playList config, here is the content
val playlistConfig = PlaylistConfig(
playlistJwPlayer,
PlaylistOptions(
preloadAllSources = false
)
)
//New Player instance & add player to Player View.
val player = Player.create(this, playerConfig = playerConfig).also {
bView.bitmovinPlayerView.player = it
}
- Autoplay is enabled via PlaybackConfig
- Android Version: 12 - Real Device - Moto G30
The way we can reproduce the issue, is just playing any content and sending it to Chromecast. Then reentering the PlayerView Activity and Pausing/Resuming the ads when they are played with Chromecast on.
Thanks in advance
Thanks @gledezma for sharing the information. A few observations, questions and suggestions.
-
The shared VAST Ad Riivi Vast does not work for me but this should not be a bottleneck at the moment.
-
I tried the use case with Bitmovin player sample including default Bitmovin player UI and am not able to reproduce the behaviour. Did you also check with default Bitmovin UI and are you able to reproduce the same behaviour?
-
You are using
isUiEnabled = false
, inStyleConfig
. Does this mean that your application is using custom Native player UI instead of Bitmovin player UI? If yes,- Can you please share what does
bView.bitmovinPlayerView
represent in your application? - Can you please share the PlayerActivity’s layout resource file?
- Can you please share what does
-
Additionally, you seem to create
Player
object explicitly in code usingPlayer.create
API. This is correct but if you are usingPlayerView
as part of your player activity’s layout, please addapp:initialize_player="false"
attribute to prevent the default Player object from being created implicitly. This is demonstarted in BasicPlaybackKotlin public sample app.
<com.bitmovin.player.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
app:initialize_player="false">
- The params
replaceContentDuration = 0.0, preloadOffset = 1.0
inAdItem
are not needed for preroll Ad. Although I do not suspect these to be root cause, but to rule this out, can you please try without these params?
I hope above information helps. Please try out above suggestions and also share your feedback about questions.
Yes, we are using a custom overlay layout
bView.bitmovinPlayerView
is the Bitmovin PlayerView component from the lib.
This is the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parentPlayer"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.bitmovin.player.PlayerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/bitmovinPlayerView"
app:initialize_player="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.bitmovin.player.PlayerView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<RelativeLayout
android:layout_width="400dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="@android:color/transparent"
android:id="@+id/playerContainer">
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/playerUI"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:animateLayoutChanges="true"
android:focusable="true">
<ImageButton
android:id="@+id/playButton"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerInParent="true"
android:background="@android:color/transparent"
android:contentDescription="@null"
android:foreground="@drawable/ripple_button_player"
android:insetLeft="0dp"
android:insetTop="0dp"
android:insetRight="0dp"
android:insetBottom="0dp"
android:src="@drawable/ic_play_button" />
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonBack"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:insetLeft="0dp"
android:insetTop="0dp"
android:insetRight="0dp"
android:insetBottom="0dp"
app:backgroundTint="@android:color/transparent"
app:cornerRadius="25dp"
app:icon="@drawable/ic_button_back"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="50dp"
app:iconTint="@android:color/white"
app:rippleColor="@color/brand_primary_opacity_input" />
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonToStart"
style="@style/Widget.MaterialComponents.Button.TextButton.Icon"
android:layout_width="186dp"
android:layout_height="52dp"
android:layout_marginStart="21dp"
android:layout_marginTop="8dp"
android:layout_toEndOf="@+id/buttonBack"
android:contentDescription="@null"
android:text="@string/fromBeginning"
android:textAllCaps="false"
android:textColor="@android:color/white"
android:textSize="14sp"
android:visibility="gone"
app:backgroundTint="#14FFFFFF"
app:cornerRadius="21dp"
app:icon="@drawable/ic_goback"
app:iconSize="14dp"
app:iconTint="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rippleColor="@color/brand_primary_opacity_input"
app:shapeAppearance="@style/fromBeginning"
tools:visibility="visible" />
<ImageView
android:id="@+id/riiviLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="12dp"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_riivi_logo_player" />
<TextView
android:id="@+id/playerTitle"
style="@style/PlayerTitle"
android:layout_width="wrap_content"
android:layout_height="28dp"
android:layout_above="@+id/playerSerieTitle"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:gravity="center_vertical|start"
tools:text="Título de Contenido" />
<TextView
android:id="@+id/playerSerieTitle"
style="@style/PlayerSerieTitle"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:gravity="center_vertical|start"
android:layout_above="@+id/playerControl"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text=""
android:visibility="gone"
tools:text="Título de Contenido" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/buttonNextEp"
style="@null"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/playerControl"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
android:layout_marginTop="6dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_button_next_ep">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@android:color/transparent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_semibold"
android:gravity="center"
android:padding="6dp"
android:background="@android:color/transparent"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginStart="8dp"
android:text="@string/btnNextEpisode"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@drawable/ic_play_margin_left" />
</LinearLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<RelativeLayout
android:id="@+id/thumbnail"
android:layout_above="@+id/playerControl"
android:layout_width="102dp"
android:layout_height="62dp"
android:visibility="invisible"
android:background="@drawable/thumbnail_frame">
<ImageView
android:id="@+id/thumbnailImg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_margin="2dp"
android:scaleType="centerCrop" />
</RelativeLayout>
<LinearLayout
android:id="@+id/playerControl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginTop="8dp"
android:gravity="center_horizontal"
android:orientation="vertical"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/positionView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingStart="16dp"
android:paddingEnd="4dp"
android:includeFontPadding="false"
android:textColor="@android:color/white"
android:text="00:00" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="14dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="@android:color/transparent"
android:thumb="@drawable/ic_thumb"
android:progressDrawable="@drawable/gradient_player_seekbar"
tools:progress="30"
tools:secondaryProgress="40"/>
<TextView
android:id="@+id/durationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingStart="4dp"
android:paddingEnd="16dp"
android:includeFontPadding="false"
android:textColor="@android:color/white"
android:text="00:00" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/buttonSubtitle"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="12dp"
android:background="@android:color/transparent"
android:foreground="@drawable/ripple_button_player"
android:visibility="gone"
android:src="@drawable/ic_subs"
tools:visibility="visible"/>
<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/buttonChromecast"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:background="@android:color/transparent"
android:foreground="@drawable/ripple_button_player"
android:src="@drawable/ic_chromecast"
android:visibility="gone"
tools:visibility="visible" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/containerSuggestEpisode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<include
android:id="@+id/itemSuggestEpisode"
layout="@layout/item_suggest_episode"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
We have some additional buttons like back button, return to the start and next episode that are over the PlayerView. The RelativeLayout
with android:id="@+id/playerUI"
is the overlay player controls. The RelativeLayout
with android:id="@+id/playerContainer"
is the subtitle view container.
Also: we tried with and without replaceContentDuration = 0.0, preloadOffset = 1.0
params. Same issue. And we are not setting an additional AdViewGroup via API.
Hi @gledezma . Thanks for sharing the Player view information. There are couple of observations/questions.
-
You mentioned earlier that way to reproduce the issue, you need to re-enter PlayerView and pausing/resuming Ads. In general casting UX, when the content is casted, player does not show playback controls for local playback but instead cast UI to control casting playback. You can check this with BasicCastingSample. So it is not clear why in your UX, the app allows to control playback of local player.
-
Do you destroy and re-create player object when exiting and returning to player activity or do you re-use the previously created player object? In either case, on re-entering the PlayerView when casting is already started earlier, then the player view should show cast UI instead of local playback controls.
-
Can you test with BasicCastingSample and check if you are able to reproduce the issue. You can also check the cast UX and compare with your application.
-
Please do also test with the latest (3.24.1) player SDK.