Làm cách nào để giảm âm lượng của luồng nhạc nền khi phát một nguồn âm thanh khác?


7

Với PulseAudio có thể quản lý âm lượng trên cơ sở ứng dụng, nhưng tôi thấy hầu như không hữu ích khi thực hiện thủ công. Những gì tôi muốn có là như sau: Tôi thường nghe nhạc nhưng đôi khi tôi muốn xem video YouTube - sau đó tôi phải tạm dừng hoặc giảm âm lượng nhạc theo cách thủ công, thường thì tôi quên bật lại khi video kết thúc

Tôi cần làm gì để tự động giảm âm lượng của luồng âm thanh (nhạc nền) khi một ứng dụng khác phát âm thanh?


2
Điều này được gọi là "vịt âm thanh". Tôi đã không chơi với chính nó, vì vậy không thể viết ra câu trả lời, nhưng đây là một số tài liệu: freedesktop.org/wiki/Software/PulseAudio/Documentation/User/, ... cái mỏ neo đó trông không đáng tin, đó là phần "mô-đun đóng vai".
derobert

Câu trả lời:


2

Không có nhiều câu trả lời, nhưng tôi cũng có thể mô tả các vấn đề / khả năng tôi tìm thấy.

Tôi không thể thấy bất kỳ cách nào để viết một kịch bản shell cho điều này. Không có cách (tài liệu) để thay đổi trên mỗi khối lượng ứng dụng bằng cách sử dụng pactl/ pacmd. Tôi cũng không thể thấy bất kỳ cách nào để biết khi nào một khách hàng mới được thêm vào mà không liên tục bỏ phiếu với nội dung như:

pactl list short clients

Âm thanh xung có thể được đặt để đăng nhập syslog, vì vậy một khả năng là có một tập lệnh được gọi qua rsyslog(nếu bản phân phối có nó). Xem câu trả lời của tôi ở đây cho một chỉ dẫn về cách làm điều này. Điều này tất nhiên phụ thuộc vào pulseaudiothông tin đăng nhập về khách hàng mới.

Điều này chắc chắn là có thể thực hiện được, pavucontrolchương trình là một ví dụ tuyệt vời về loại điều này đang được thực hiện. Tuy nhiên, hiện tại có vẻ như không có CLI để làm những thứ tương tự, vì vậy nó có thể sẽ yêu cầu giao diện trực tiếp hơn với pulseaudioAPI.

Cập nhật

Nhìn vào liên kết của @ derobert , mô-đun đóng vai trò sẽ đủ dễ để kích hoạt, nhưng nó yêu cầu media.rolecác thuộc tính chỉ định . Dù sao tôi cũng không thể tìm thấy những thứ này là gì! Có khả năng là chúng không được xác định cho nhiều luồng (nhiều chương trình vẫn nghĩ rằng chúng đang sử dụng ALSA). Nếu có một số cách liệt kê những thứ này và có thể cấu hình chúng để được chỉ định (có thể dựa trên tên của quy trình), đây sẽ là cách dễ nhất.

Cập nhật 2

media.rolecó thể được thiết lập thông qua các PULSE_PROPbiến môi trường. Ví dụ:

PULSE_PROP='media.role=music' play some_music.mp3 &
pactl list clients | grep -C 10 'media.role = "music"'

Điều này có thể được đặt cho một ứng dụng khác bằng cách chỉnh sửa .desktoptệp và / hoặc tạo tập lệnh bao bọc, nhưng điều này có vẻ không phải là một cách rất tốt.


3
Có một CLI được ghi nhận để thay đổi khối lượng trên mỗi khách hàng ... Ví dụ: pactl set-sink-input-volume 1384 100%trong đó 1384 là số máy khách. Bí mật là chúng được gọi là "đầu vào chìm" để phát lại ứng dụng khách (và đầu ra nguồn để ghi ứng dụng khách).
derobert

1
@derobert điều này không hoạt động, nhưng đối với tôi không phải với số khách hàng. Nếu tôi sử dụng số đầu vào chìm pactl list sink-inputsthay vì số máy khách, thì nó hoạt động. clientdường như là một nhóm rộng hơn sink-inputvì nó bao gồm nhiều hơn là các ứng dụng phát âm thanh. Tôi không thể tìm thấy bất kỳ tài liệu âm thanh xung nào trong đó các thuật ngữ này được xác định đúng.
Graeme

1

Các gợi ý trong nhận xét của @derobert và @ Graeme rất hữu ích, nhưng định dạng đầu ra không thuận tiện, vì vậy tôi đã viết một trình phân tích cú pháp để chuyển đổi nó thành 0 Name 0.0, dễ phân tích hơn. Trong khi làm như vậy, tôi cũng đã thêm một trình trợ giúp để thay đổi âm lượng dễ dàng.

Có thể nhúng nó vào một vòng lặp và làm bất cứ điều gì bạn muốn. Đây là ngôn ngữ Nim .

import osproc, strutils, pegs, os, parseopt2, sequtils

type Application = object
  id: int
  name: string
  volume: float

var verbose = false

proc tryExec(cmd): auto =
  if verbose: echo("executing $1" % [cmd])
  let output = execCmdEx(cmd)
  if output.exitCode != 0:
    raise newException(EBase, "Failed to execute `$1` with error code $2\nOutput:\n===\n$3\n===" %
                              [cmd, $output.exitCode, output.output])
  return output.output

iterator getPlayingApps(): auto =
  let paOutput = tryExec("pactl list sink-inputs")

  let sinkStrings = paOutput.split("\l\l")

  for str in sinkStrings:
    var num: int
    var volume: float
    var applicationName: string

    var matches = ["", ""]

    if str.find(peg"'Sink Input #'{\d+}", matches) != -1:
      num = parseInt(matches[0])
    else:
      raise newException(EBase, "Could not find sink input number in \n===\n$1" % [str])

    if str.find(peg"'Volume'@'/'\s*{\d+}'%'", matches) != -1:
      volume = parseFloat(matches[0])
    else:
      raise newException(EBase, "Could not find application volume in \n===\n$1" % [str])

    if str.find(peg"'application.name = ""'{[^""]+}'""'", matches) != -1:
      applicationName = matches[0]
    else:
      raise newException(EBase, "Could not find application name in \n===\n$1" % [str])

    yield Application(id: num, name: applicationName, volume: volume)

proc adjustAppVolume(app: Application, percent: float) =
  let nextVol = min((app.volume + (app.volume * (percent - 100) / 100.0)).int, 100)
  discard tryExec("pactl set-sink-input-volume $1 $2%" % [$app.id, $nextVol])

proc adjustName(name: string, percent: float) =
  for app in getPlayingApps():
    if app.name.contains(peg(name)):
      adjustAppVolume(app, percent)

proc printInfo() =
  for app in getPlayingApps():
    echo("$1\t$2\t$3" % [$app.id, app.name, $app.volume])

var params: seq[string] = @[]
for kind, key, val in getopt():
  case kind
  of cmdArgument:
    params.add(key)
  of cmdLongOption, cmdShortOption:
    case key
    of "help", "h":
      echo "usage: parsepa [-h|--help] [-v|--verbose] [<name expression> percent (-a|--adjust)] [-p|--print]"
      quit(QuitSuccess)
    of "verbose", "v":
      verbose = true
    of "adjust", "a":
      adjustName(params[0], parseFloat(params[1]))
      quit(QuitSuccess)
    of "print", "p":
      printInfo()
      quit(QuitSuccess)
    else:
      echo "Invalid Argument"
      quit(QuitFailure)
  else:
    echo "Invalid Argument"
    quit(QuitFailure)

x64 nhị phân trong ý chính này, dành cho người lười biếng: https://gist.github.com/flaviut/9feb9a75bd452e6ddd03

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.