به اشتراک گذاری ورودی صوتی

ورودی صدا معمولاً از میکروفون داخلی، یک میکروفون خارجی یا یک رابط صوتی متصل به دستگاه می آید. ورودی صوتی نیز می تواند از یک مکالمه تلفنی باشد.

گاهی اوقات ممکن است دو یا چند برنامه هر دو بخواهند ورودی صوتی یکسانی را ضبط کنند. آنها ممکن است وظایف مختلفی را انجام دهند. به عنوان مثال، برخی از برنامه‌هایی که صدا را دریافت می‌کنند ممکن است در حال «ضبط کردن» باشند، مانند یک ضبط صوت ساده، در حالی که برنامه‌های دیگر ممکن است در حال «گوش دادن» باشند، مانند Google Assistant یا یک سرویس دسترسی که به دستورات صوتی پاسخ می‌دهند.

در هر صورت، این برنامه ها می خواهند ورودی صوتی را دریافت کنند. در سرتاسر این صفحه، صرف نظر از اینکه برنامه در حال ضبط است یا فقط گوش می دهد، از عبارت «کپچر» استفاده می کنیم.

اگر دو یا چند برنامه بخواهند همزمان صدا را ضبط کنند، ممکن است مشکلی در ارائه سیگنال صوتی از یک منبع به همه آنها وجود داشته باشد. این صفحه نحوه اشتراک‌گذاری ورودی صوتی را بین چندین برنامه که صدا را ضبط می‌کنند، توسط سیستم Android به اشتراک می‌گذارد.

رفتار قبل از اندروید 10

قبل از Android 10، جریان صوتی ورودی را فقط یک برنامه در هر زمان می‌توان ضبط کرد. اگر برنامه‌ای قبلاً صدا را ضبط یا گوش می‌داد، برنامه شما می‌تواند یک شی AudioRecord ایجاد کند، اما با فراخوانی AudioRecord.startRecording() خطایی برمی‌گردد و ضبط شروع نمی‌شود.

یکی از استثناهای این قانون زمانی بود که یک برنامه ممتاز (مانند Google Assistant یا یک سرویس دسترسی) مجوز android.permission.CAPTURE_AUDIO_HOTWORD را داشت و از منبع صوتی از نوع HOTWORD استفاده می کرد. در این حالت برنامه دیگری می تواند ضبط را شروع کند. وقتی این اتفاق افتاد، برنامه ممتاز خاتمه یافت و برنامه جدید ورودی را ضبط کرد.

یک تغییر دیگر در اندروید 9 اضافه شد: فقط برنامه‌هایی که در پیش‌زمینه اجرا می‌شوند (یا یک سرویس پیش‌زمینه) می‌توانند ورودی صدا را ضبط کنند. هنگامی که برنامه‌ای بدون سرویس پیش‌زمینه یا مؤلفه رابط کاربری پیش‌زمینه شروع به ضبط می‌کرد، برنامه همچنان به کار خود ادامه می‌داد اما سکوت دریافت می‌کرد، حتی اگر در آن زمان تنها اپلیکیشنی بود که صدا را ضبط می‌کرد.

رفتار اندروید 10

رفتار قبل از اندروید 10 به این صورت است که «اولین حضور، اولین خدمت» است. هنگامی که برنامه شروع به ضبط صدا می کند، هیچ برنامه دیگری نمی تواند به ورودی صوتی دسترسی داشته باشد تا زمانی که برنامه ضبط صدا متوقف شود.

اندروید 10 یک طرح اولویت را اعمال می کند که می تواند جریان صوتی ورودی را بین برنامه ها در حین اجرا تغییر دهد. در بیشتر موارد، اگر یک برنامه جدید ورودی صدا را دریافت کند، برنامه ضبط شده قبلی به کار خود ادامه می دهد، اما سکوت را دریافت می کند. در برخی موارد، سیستم می‌تواند به ارائه صدا به هر دو برنامه ادامه دهد. سناریوهای مختلف اشتراک گذاری در زیر توضیح داده شده است.

این طرح مشابه روشی است که فوکوس صوتی چندین برنامه را که برای استفاده از خروجی صدا مدعی هستند، کنترل می کند. با این حال، فوکوس صوتی توسط درخواست‌های برنامه‌ای برای به دست آوردن و رها کردن فوکوس مدیریت می‌شود، در حالی که طرح تعویض ورودی که در اینجا توضیح داده شده است بر اساس یک خط‌مشی اولویت‌بندی است که هر زمان که برنامه جدیدی شروع به ضبط صدا کند، به‌طور خودکار اعمال می‌شود.

برای ضبط صدا، اندروید دو نوع برنامه را متمایز می کند:

  • برنامه های "معمولی" توسط کاربر نصب می شوند.
  • برنامه های «ممتاز» از قبل روی دستگاه نصب شده اند. اینها شامل Google Assistant و همه خدمات دسترسی است.

به‌علاوه، اگر از یک منبع صوتی «حساس به حریم خصوصی» استفاده کند: CAMCORDER یا VOICE_COMMUNICATION با یک برنامه رفتار متفاوتی می‌شود.

قوانین اولویت بندی برای استفاده و اشتراک گذاری ورودی صوتی به شرح زیر است:

  • برنامه های دارای امتیاز اولویت بالاتری نسبت به برنامه های معمولی دارند.
  • برنامه‌های دارای رابط کاربری پیش‌زمینه قابل مشاهده، اولویت بیشتری نسبت به برنامه‌های پس‌زمینه دارند.
  • برنامه‌هایی که صدا را از منبع حساس به حریم خصوصی ضبط می‌کنند نسبت به برنامه‌هایی که نیستند اولویت بیشتری دارند.
  • دو برنامه معمولی هرگز نمی توانند همزمان صدا ضبط کنند.
  • در برخی شرایط، یک برنامه ممتاز می تواند ورودی صوتی را با برنامه دیگری به اشتراک بگذارد.
  • اگر دو برنامه پس‌زمینه با اولویت یکسان در حال ضبط صدا هستند، آخرین موردی که شروع شده اولویت بیشتری دارد.

به اشتراک گذاری سناریوها

هنگامی که دو برنامه سعی در ضبط صدا دارند، ممکن است هر دو بتوانند سیگنال ورودی را دریافت کنند یا یکی از آنها ممکن است سکوت را دریافت کند.

چهار سناریو اصلی وجود دارد:

  • دستیار + برنامه معمولی
  • سرویس دسترسی + برنامه معمولی
  • دو برنامه معمولی
  • تماس صوتی + برنامه معمولی

دستیار + برنامه معمولی

Assistant یک برنامه ممتاز است زیرا از قبل نصب شده است و نقش RoleManager.ROLE_ASSISTANT را دارد. با هر برنامه از پیش نصب شده دیگری که این نقش را داشته باشد به طور مشابه رفتار می شود.

Android صدای ورودی را طبق این قوانین به اشتراک می گذارد:

  • دستیار می‌تواند صدا را دریافت کند (مهم نیست در پیش‌زمینه یا پس‌زمینه باشد)، مگر اینکه برنامه دیگری که از منبع صوتی حساس به حریم خصوصی استفاده می‌کند در حال ضبط باشد.

  • برنامه صدا را دریافت می کند مگر اینکه دستیار یک مؤلفه رابط کاربری قابل مشاهده در بالای صفحه داشته باشد.

توجه داشته باشید که هر دو برنامه فقط زمانی صدا را دریافت می‌کنند که دستیار در پس‌زمینه باشد و برنامه دیگر از منبع صوتی حساس به حریم خصوصی ضبط نمی‌کند.

سرویس دسترسی + برنامه معمولی

یک AccessibilityService به یک اعلامیه دقیق نیاز دارد.

Android صدای ورودی را طبق این قوانین به اشتراک می گذارد:

  • اگر رابط کاربری سرویس در بالا باشد، هم سرویس و هم برنامه ورودی صوتی را دریافت می کنند. این رفتار عملکردهایی مانند کنترل تماس صوتی یا ضبط ویدیویی با دستورات صوتی را ارائه می دهد.

  • اگر سرویس در بالا نباشد، با این مورد مانند مورد معمولی دو برنامه زیر رفتار می شود.

دو برنامه معمولی

هنگامی که دو برنامه همزمان عکس می گیرند، فقط یک برنامه صدا را دریافت می کند و دیگری سکوت می کند.

Android صدای ورودی را طبق این قوانین به اشتراک می گذارد:

  • اگر هیچ یک از برنامه ها به حریم خصوصی حساس نباشد، برنامه با رابط کاربری در بالا صدا را دریافت می کند. اگر هیچ‌یک از برنامه‌ها رابط کاربری نداشته باشند، برنامه‌ای که اخیراً ضبط را شروع کرده، صدا را دریافت می‌کند.
  • اگر یکی از برنامه‌ها به حریم خصوصی حساس باشد، صدا را دریافت می‌کند و برنامه دیگر خاموش می‌شود، حتی اگر یک رابط کاربری در بالا داشته باشد یا اخیراً شروع به ضبط کرده باشد.
  • اگر هر دو برنامه به حریم خصوصی حساس باشند، برنامه‌ای که اخیراً شروع به ضبط کرده است صدا را دریافت می‌کند و دیگری بی‌صدا می‌شود.

تماس صوتی + برنامه معمولی

اگر حالت صوتی ارسال شده توسط AudioManager.getMode() MODE_IN_CALL یا MODE_IN_COMMUNICATION باشد، تماس صوتی فعال است.

Android صدای ورودی را طبق این قوانین به اشتراک می گذارد:

رفتار اندروید 11

Android 11 (سطح API 30) طرح اولویت Android 10 را که در بالا توضیح داده شد رعایت می کند. همچنین روش‌های جدیدی را در AudioRecord ، MediaRecorder و AAudioStream ارائه می‌کند که امکان ضبط همزمان صدا را بدون در نظر گرفتن موارد استفاده انتخابی، فعال و غیرفعال می‌کند.

روش های جدید عبارتند از:

وقتی setPrivacySensitive() true باشد، مورد استفاده از ضبط خصوصی است و حتی یک دستیار ممتاز نمی تواند همزمان عکس بگیرد. این تنظیم رفتار پیش‌فرض را که به منبع صوتی بستگی دارد لغو می‌کند. برای مثال، VOICE_COMMUNICATION به طور پیش‌فرض خصوصی است، اما UNPROCESSED اینطور نیست.

تغییرات پیکربندی

هنگامی که چندین برنامه به طور همزمان صدا را ضبط می کنند، تنها یک یا دو برنامه "فعال" هستند (دریافت صدا). بقیه خاموش می شوند (در حال دریافت سکوت). وقتی برنامه‌های فعال تغییر می‌کنند، چارچوب صوتی ممکن است مسیرهای صوتی را طبق این قوانین مجدداً پیکربندی کند:

  • دستگاه ورودی صدا برای هر برنامه فعال ممکن است تغییر کند (به عنوان مثال، از میکروفون داخلی به هدست بلوتوث متصل).
  • پیش پردازش مرتبط با برنامه فعال با بالاترین اولویت فعال است. تمام پیش پردازش های دیگر نادیده گرفته می شود.

از آنجایی که ممکن است یک برنامه فعال با فعال شدن یک برنامه با اولویت بالاتر خاموش شود، می توانید یک AudioManager.AudioRecordingCallback را در شئ AudioRecord یا MediaRecorder ثبت کنید تا هنگام تغییر پیکربندی مطلع شوید. تغییرات احتمالی می تواند باشد:

  • ضبط بدون صدا یا بی صدا
  • دستگاه تغییر کرد
  • پیش پردازش تغییر کرد
  • ویژگی‌های جریان تغییر کرد (نرخ نمونه‌برداری، ماسک کانال، قالب نمونه)

قبل از شروع ضبط، باید AudioRecord.registerAudioRecordingCallback() را فراخوانی کنید. پاسخ تماس تنها زمانی اجرا می شود که برنامه در حال دریافت صدا باشد و تغییری رخ دهد.

متد onRecordingConfigChanged() یک AudioRecordingConfiguration حاوی وضعیت ضبط صوتی فعلی را برمی گرداند. از روش های زیر برای اطلاع از تغییر استفاده کنید:

isClientSilenced()
اگر صدای بازگردانده شده به مشتری در حال حاضر به دلیل خط مشی ضبط خاموش باشد، درست برمی گردد.
getAudioDevice()
دستگاه صوتی فعال را برمی گرداند.
getEffects()
اثر پیش پردازش فعال را برمی گرداند. توجه داشته باشید که اگر کلاینت برنامه فعال با بالاترین اولویت نباشد، ممکن است افکت فعال با آنچه که توسط getClientEffects() برگردانده شده باشد، نباشد.
getFormat()
ویژگی های جریان را برمی گرداند. توجه داشته باشید که داده‌های صوتی واقعی دریافت‌شده توسط کلاینت همیشه به فرمت مورد نیاز بازگشت‌شده توسط getClientFormat() احترام می‌گذارد. چارچوب به طور خودکار نمونه‌برداری مجدد، کانال و تبدیل فرمت لازم را از فرمت مورد استفاده در رابط سخت‌افزاری به فرمت مشخص شده توسط مشتری انجام می‌دهد.
AudioRecord.getActiveRecordingConfiguration() .
پیکربندی ضبط فعال را برمی‌گرداند.

می‌توانید با فراخوانی AudioManager.getActiveRecordingConfigurations() یک نمای کلی از تمام ضبط‌های فعال در دستگاه دریافت کنید.