简体   繁体   English

如何修复“视频播放但在 iOS 上没有声音”

[英]How to fix 'Video play but don't have sound on iOS with expo'

I use video component from expo. I can play video, but it doesn't sound in iOS. In Android it's okay.我用的是expo的视频组件,可以播放视频,但是iOS没有声音,Android没问题。 How can I fix it.我该如何解决。

<Video style={{ width: 340, 
                                height: 220,
                                borderRadius: 10, 
                                overflow: 'hidden' }}
                                posterSource={require('../../assets/loading2.gif')}
                                usePoster={true}
                                rate={1.0}
                                isMuted={false}
                                useNativeControls = {true}
                                volume={1.0}
                                playsInSilentLockedModeIOS ={ true }
                                resizeMode='cover' 
                                shouldPlay={true} 
                                source={{uri : url}} />

Enabling background audio is not the solution (especially if you are using a managed Expo project where messing with Xcode settings is not ideal).启用背景音频不是解决方案(特别是如果您使用的是托管的 Expo 项目,其中 Xcode 设置并不理想)。 I found that the bug exists when you use useNativeControls={true} and do not auto play the video.我发现当您使用useNativeControls={true}并且不自动播放视频时存在该错误。 If you try shouldPlay={true} you should see it working.如果你尝试shouldPlay={true}你应该看到它工作。 That's not a great solution (auto playing video is very MySpace circa 2005).这不是一个很好的解决方案(自动播放视频是大约 2005 年的 MySpace)。

I fixed it by putting an overlay over the video screen with a custom play button.我通过使用自定义播放按钮在视频屏幕上放置覆盖层来修复它。 For some reason calling play from the video ref uses the correct sound profile.出于某种原因,从视频参考调用播放使用正确的声音配置文件。

  const videoRef = React.useRef<Video>()

  React.useEffect(() => {
    const enableAudio = async () => {
        await Audio.setAudioModeAsync({
        allowsRecordingIOS: false,
        interruptionModeIOS: INTERRUPTION_MODE_IOS_DO_NOT_MIX,
        playsInSilentModeIOS: true,
        staysActiveInBackground: false,
        interruptionModeAndroid: INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
        shouldDuckAndroid: false,
      })
    }
    enableAudio()
  }, [])

  const play = () => videoRef.current && videoRef.current.playAsync()

  const poster = (
      <View position="absolute" flexible="column-center" bg="transparent">
        <IconButton
          name="play"
          onPress={play}
          size={72}
          iconSize={72}
          bg="transparent"
          iconColor="rgba(255,255,255,0.9)"
        />
      </View>
    )

  return (
    <View>
      <VideoPlayer
        ref={videoRef}
        source={R.is(String, props.asset) ? { uri: props.asset } : props.asset}
        shouldPlay={props.autoPlay !== false}
        useNativeControls={true}
        rate={1.0}
        volume={1.0}
        resizeMode={Video.RESIZE_MODE_CONTAIN}
      />
      <View position="absolute" flexible="column-center" bg="transparent">
        <IconButton
          name="play"
          onPress={play}
          size={72}
          iconSize={72}
          bg="transparent"
          iconColor="rgba(255,255,255,0.9)"
        />
      </View>
    </View>
  )

The audio wasn't working because I had my phone on silent.音频无法正常工作,因为我的手机处于静音状态。 To change this default behaviour, set playsInSilentLockedModeIOS={ true } .要更改此默认行为,请设置playsInSilentLockedModeIOS={ true }

(I know OP already has this in their code, but I'm answering just in case this helps someone). (我知道 OP 在他们的代码中已经有了这个,但我会回答以防万一这对某人有帮助)。

I was having this issue due to the silent switch on the side of the iPhone being enabled.由于启用了 iPhone 侧面的静音开关,我遇到了这个问题。 To have the video player play sound I needed to included the following as a prop to the video component.为了让视频播放器播放声音,我需要包含以下内容作为视频组件的道具。

ignoreSilentSwitch={'ignore'}

Here's what worked for me:这是对我有用的:

  1. Create a reference ( ref ) to the <Video /> component.创建对<Video />组件的引用 ( ref )。
  2. Use a state to listen when the video starts playing.当视频开始播放时,使用 state 收听。
  3. When it does, call await Audio.setAudioModeAsync({ playsInSilentModeIOS: true });当它发生时,调用await Audio.setAudioModeAsync({ playsInSilentModeIOS: true }); . .
  4. Immediately after, re-play the video by calling ref.current.playAsync();紧接着,通过调用ref.current.playAsync();

In summary, my component looks like this:总之,我的组件如下所示:

import React, { useState, useEffect, useRef } from 'react';
import { Audio, Video as OriginalVideo } from 'expo-av';

const triggerAudio = async (ref) => {
  await Audio.setAudioModeAsync({ playsInSilentModeIOS: true });
  ref.current.playAsync();
};

const Video = ({ ...props }) => {
  const ref = useRef(null);
  const [status, setStatus] = useState({});

  useEffect(() => {
    if (status.isPlaying) triggerAudio(ref);
  }, [ref, status.isPlaying]);

  return (
    <OriginalVideo
      ref={ref}
      onPlaybackStatusUpdate={(status) => setStatus(status)}
      useNativeControls
      {...props}
    />
  );
};

Tested with Expo SDK v45 and iOS 16.使用 Expo SDK v45 和 iOS 16 进行测试。

Hope it helps!希望能帮助到你!

Determine whether the media should continue playing while the app is in the background .确定当appbackgroundmedia是否应继续播放。 This allows customers to continue listening to the audio .这允许客户继续收听audio

To use this feature on iOS , you must:要在iOS上使用此功能,您必须:

  • Enable Background Audio in your Xcode projectXcode项目中启用背景音频
  • Set the ignoreSilentSwitch prop to "ignore"将 ignoreSilentSwitch 道具设置为"ignore"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM