Play audio và audio control panel

Mình muốn play audio và hiện control panel cho audio như hình dưới thì cần phải làm như thế nào


mình đã thử code như trong mục components nhưng lại bị lỗi như này

Để làm UI như trên thì bạn nên làm hidden audio component rồi custom UI theo ý mình muốn. Khi có event trên custom UI đó có thể điều khiển hidden audio component qua jsapi này my.createAudioContext | Tini App

Còn error @hung.nguyen7 thử reproduce giúp anh.

Chào @Duc_Pham

Để fix lỗi trên audio tạm thời bạn thêm style=“padding: 0” (hoặc style bất kỳ) vào trong thẻ audio giúp mình nhé, bản release tới của studio sẽ fix lỗi này nhé

<audio src="..." style="padding: 0" />

mình đã thử play audio nhưng nó lại không chạy ._.

Bạn sửa đường dẫn thành <audio src="/audio/testmusic.mp3"/> nhé, đường dẫn tuyệt đối tính từ thư mục src

Hi anh, anh có hướng dẫn nào để làm custom UI này không ạ, em chỉ cần hiển thị phần control audio (tiến lên , lùi lại ) rồi gắn icon của button vào

Mình không copy full project được bạn tham khảo concept rồi làm tương ứng nhé:

Idea là mình hide cái audio tag để nó run background nhưng mình vẫn lắng nghe các sự kiện của nó:

      onPlay="onAudioPlay"
      onEnd="onAudioEnd"
      onPause="onAudioPause"

Mọi trigger trên custom UI mình điều khiển cái audio tag đó qua JSAPI Audio Context.

Note bạn đọc hiểu rồi copy code lại nhé, example dưới mình đang hơi bận nên chưa compile thử, nhưng concept thì đúng.

audio.txml

<!--- UI Custom Audio palyer -->
<view class="nowplaying-container">
  <view class="nowplaying-metadata">
    <view class="metadata">
      <view class="metadata-body">
        <view class="album-art">
          <image src="https://i.scdn.co/image/ab67616d00001e028ae85de1791a8d703cb57c40" />
        </view>
      </view>

      <view class="name" >
        <text>Thiên Đàng - Wowy, JoliPoli</text>
      </view>
      <view class="author">
        <text>Wowy</text>
      </view>
    </view>
  </view>
  <view class="nowplaying-controls">
    <view class="progress-bar">
      <view class="rangebar-container">
        <view class="rangebar-fill" style="width: {{progressPercent}}%"></view>
      </view>
      <view class="progress-timer">
        <text>{{progress}}</text>
        <text>{{duration}}</text>
      </view>
    </view>
    <view class="playback-controls">
      <view class="col">
        <view class="button" onTap="seekPrev">
          <image src="../../images/seek-back.svg" style="height: 24px; width: 24px" />
        </view>
      </view>

      <view class="col">
        <view class="play-button" tiki:if="{{playing}}" onTap="playPauseTap">
          <image src="../../images/pause-icon.svg"  />
        </view>

        <view class="play-button" tiki:else onTap="playPauseTap">
          <image src="../../images/play-icon.svg"  />
        </view>
      </view>

      <view class="col">
        <view class="button" onTap="seekNext">
          <image src="../../images/seek-next.svg" style="height: 24px; width: 24px" />
        </view>
      </view>
    </view>
  </view>
<!-- hidden audio -->
    <audio
      id="audio"
      poster="https://data.chiasenhac.com/data/cover/130/129107.jpg"
      loop="true"
      name="Thiên Đàng - Wowy, JoliPoli"
      author="Wowy"
      style="display: hidden"
      src="https://dev-tikiscp.tbox.vn/miniapps/miki/thiendang.mp3"
      onTimeUpdate="onAudioTimeUpdate"
      onPlay="onAudioPlay"
      onEnd="onAudioEnd"
      onPause="onAudioPause"
    />
</view>
Page({
  async onLoad() {
    this.audioContext = my.createAudioContext('#audio'));
  },
  onAudioTimeUpdate(e) {
    const { detail: { currentTime, duration } } = e;
    this.currentTime = currentTime;
    this.setData({
      progress: formatTime(currentTime),
      duration: formatTime(duration),
      progressPercent: currentTime / duration * 100,
    });
  },
  playPauseTap() {
    const playing = !this.data.playing;
    if (this.audioContext ) {
      if (playing) {
        this.audioContext .play();
      } else {
        this.audioContext .pause();
      }
    }
    this.setData({ playing })
  },
  seekNext() {
    if (this.audioContext) {
      this.audioContext.seek(this.currentTime + 10);
    }
  },
  seekPrev() {
    const audioContext = getApp().getAudioContext();
    if (this.audioContext) {
      this.audioContext.seek(this.currentTime - 10);
    }
  }
})

Hi anh ơi phần code của anh em đã thử đổi một chút và nó rất ok, cơ mà em làm cái đoạn fill progress bar theo thời gian này mãi không ra, anh có code css không ạ @@

Đây nhé @Duc_Pham

.nowplaying-container {
  padding: 16px;
}

.album-art {
  display: flex;
  align-items: center;
  position: relative;
  margin: 24px 0px;
}

.album-art image {
  object-fit: contain;
  max-height: 100%;
  position: relative;
  width: 100%;
}
.metadata {
  overflow: hidden;
}
.metadata .name {
  color: #fff;
  width: 100%;
  animation: 20.9667s linear 0s infinite normal none running moving;
  white-space: nowrap;
  margin: 0 0 16px 0;
}

@keyframes moving {
  0% { transform: translateX(0%) }
  50% { transform: translateX(0%) }
  100% { transform: translateX(-100%); }
}

.metadata .name text {
  font-size: 32px;
  font-weight: 700;
  width: 100%;
  white-space: nowrap;
}

.metadata .author text {
  color: rgb(179, 179, 179);
  margin: 0px;
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 18px;
}

.nowplaying-controls {
  margin: 16px 0px;
}

.progress-bar {
  width: 100%;
}

.progress-bar .rangebar-container {
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 2px;
  height: 4px;
  width: 100%;
  position: relative;
  transform: none;
}

.rangebar-container .rangebar-fill {
  border-radius: 2px;
  height: 100%;
  background-color: rgb(255, 255, 255);
}

.progress-timer {
  color: rgb(255, 255, 255);
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  margin-bottom: 8px;
  flex-direction: row;
}

.progress-timer text {
  font-size: 11px;
  font-weight: 400;
  line-height: 16px;
}

.playback-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: row;
}

.playback-controls .col {
  flex-basis: 20%;
  display: flex;
  justify-content: center;
  align-items: center;
}


.playback-controls .play-button {
  align-items: center;
  border-radius: 50%;
  border: none;
  background-color: rgb(255, 255, 255);
  color: rgb(0, 0, 0);
  display: flex;
  justify-content: center;
  padding: 0px;
  position: relative;
  height: 64px;
  width: 64px;
}