Đường ống với quá trình thay thế và nối lại đầu ra


2

Tôi đang cố gắng sử dụng một máy chủ từ xa mạnh mẽ về mặt mã hóa video.

Tôi có một ổ đĩa DVD cục bộ để trích xuất DVD vào bộ nhớ, cuối cùng nằm trong một mbuffer.

Từ đó, tôi muốn phân chia luồng, chuyển hướng luồng video thô qua mạng đến tác nhân từ xa để mã hóa và dẫn luồng kết quả trở lại, đồng thời, chuyển đổi luồng âm thanh cục bộ sang luồng định dạng khác. Sau đó, cuối cùng, tôi muốn tham gia cả hai luồng kết quả vào một tệp mới.

Một phần của điều này có thể được giải quyết bằng cách teenhập nội dung mbuffer và chuyển hướng thích hợp:

(reading commands) | mbuffer -p 1 -m 5G | tee <(ffmpeg -i - (splitting video stream here) -f avi | ssh 1.2.3.4 'ffmpeg -i - (doing some encoding here) -f <format> - ') | <( ffmpeg -i (processing audio adequately) )

nhưng điều này khiến tôi có hai đường ống được chuyển hướng mà không có sự phân tách hợp lý. Rõ ràng: làm thế nào để tôi tham gia lại cả hai luồng (tôi cần nhận các luồng đầu vào riêng biệt cho một lệnh khác : ffmpeg -i <s -tream1> -i <stream2> (doing final conversion) ? Có cơ hội nào để làm điều đó không?

Câu trả lời:


2

Tôi không hoàn toàn hiểu lệnh nhưng mô tả của bạn có vẻ như đó có thể là một công việc cho các đường ống được đặt tên. Để làm cho khái niệm này rõ ràng ví dụ của tôi sử dụng bốn trong số họ. Với sự thay thế phù hợp, bạn có thể giảm con số này xuống còn hai, tôi nghĩ, thậm chí có thể là một; nhưng bây giờ hãy giữ nó đơn giản.

mkfifo pre-audio-pipe pre-video-pipe audio-pipe video-pipe # creating pipes
(reading commands) | mbuffer -p 1 -m 5G | tee pre-audio-pipe > pre-video-pipe # splitting

Quá trình này sẽ điền vào bất cứ bộ đệm nào được tạo cho hai ống được đặt tên, sau đó nó sẽ chờ dữ liệu này được đọc ở nơi khác.

"Nơi khác" nằm trong bảng điều khiển khác:

<pre-audio-pipe (isolate audio) | (process audio) > audio-pipe

và trong một giao diện điều khiển khác:

<pre-video-pipe (isolate video) | (process video) > video-pipe

Một lần nữa hai lệnh này sẽ đợi cho đến khi chúng ta đọc một số dữ liệu từ các đường ống. Trong bảng điều khiển cuối cùng:

ffmpeg -i video-pipe -i audio-pipe (doing final conversion)

Bạn có thể gặp phải tình trạng khóa máy trong trường hợp lệnh cuối cùng muốn đọc một luồng trước luồng khác. Tôi không biết khả năng này là như thế nào. Bộ đệm bổ sung có thể hữu ích để tránh điều này. Thử nghiệm đầu tiên của tôi sẽ là loại bỏ mbuffer(trước tee) và chèn hai bộ đệm độc lập giữa tương ứng (isolate)(process).

Sau khi xong tất cả:

rm pre-audio-pipe pre-video-pipe audio-pipe video-pipe # cleaning

Biên tập

Từ bình luận của OP:

Bạn có thấy bất kỳ cơ hội để thực hiện một giải pháp mà không sử dụng các ống có tên riêng biệt không?

Tôi đã suy nghĩ về coprocesses ( coprocdựng sẵn) nhưng tôi không biết nhiều về chúng. Có câu trả lời toàn diện về họ. Tìm kiếm cụm từ "tại sao chúng không phổ biến". Từ đó:

Lợi ích duy nhất của việc sử dụng coproclà bạn không phải dọn sạch những ống có tên sau khi sử dụng.

Tôi hoàn toàn đồng ý. Nhìn vào ví dụ ở đó - về cơ bản là trường hợp của bạn với luồng dữ liệu rẽ ba chiều thay vì hai chiều. Ví dụ này sử dụng các shell khác bashnhưng theo kinh nghiệm của tôi thì nó cũng tương tự khủng khiếp bash.

Lý tưởng nhất là sẽ chỉ có một dòng lệnh làm việc với các ống không tên, vì công việc nên được bắt đầu bằng một "nỗ lực kinh tế" từ dấu nhắc lệnh.

Nghiêm túc? Với tất cả những người (doing some encoding here)mở rộng? Theo tôi, bất kể bạn sử dụng các ống có tên hay không tên, "nỗ lực kinh tế" ở đây sẽ là viết kịch bản, ngay cả khi đó là công việc một lần. So sánh kịch bản một đoạn dài và tương đương được viết tốt, tôi thấy phần sau dễ gỡ lỗi hơn.

Nhưng vì bạn đã yêu cầu một lớp lót, bạn sẽ nhận được nó , vẫn với các ống được đặt tên mặc dù. Ý tưởng của tôi để duy trì các đường ống được đặt tên là tạo một thư mục tạm thời cho chúng. Khái niệm chung:

my_temp=`mktemp -d` ; pre_audio_pipe="${my_temp}/pre-audio-pipe" ; pre_video_pipe="${my_temp}/pre-video-pipe" ; audio_pipe="${my_temp}/audio-pipe" ; video_pipe="${my_temp}/video-pipe" ; mkfifo "$pre_audio_pipe" "$pre_video_pipe" "$audio_pipe" "$video_pipe" ; (reading commands) | tee "$pre_audio_pipe" > "$pre_video_pipe" & <"$pre_audio_pipe" (isolate audio) | mbuffer -p 1 -m 1G | (process audio) > "$audio_pipe" & <"$pre_video_pipe" (isolate video) | mbuffer -p 1 -m 4G | (process video) > "$video_pipe" & ffmpeg -i "$video_pipe" -i "$audio_pipe" (doing final conversion) ; rm -rf "$my_temp"

Theo câu trả lời này, có lẽ bạn có thể điều chỉnh nó thành một dòng lệnh, ngay cả sau khi bạn đào sâu vào lệnh và mở rộng tất cả các (do something)trình giữ chỗ đó.

OK, hình thức một lớp lót là để cho bạn thấy nó bất tiện như thế nào. Khái niệm tương tự như một kịch bản:

#!/bin/bash

my_temp=`mktemp -d`
pre_audio_pipe="${my_temp}/pre-audio-pipe"
pre_video_pipe="${my_temp}/pre-video-pipe"
audio_pipe="${my_temp}/audio-pipe"
video_pipe="${my_temp}/video-pipe"

mkfifo "$pre_audio_pipe" "$pre_video_pipe" "$audio_pipe" "$video_pipe" #creating actual pipes

# Main code here.
# Notice we put few commands into the background.
# In this example there are two separate mbuffers.
(reading commands) | tee "$pre_audio_pipe" > "$pre_video_pipe" & # splitting
<"$pre_audio_pipe" (isolate audio) | mbuffer -p 1 -m 1G | (process audio) > "$audio_pipe" &
<"$pre_video_pipe" (isolate video) | mbuffer -p 1 -m 4G | (process video) > "$video_pipe" &
ffmpeg -i "$video_pipe" -i "$audio_pipe" (doing final conversion)

# Then cleaning:
rm -rf "$my_temp"

Thật thú vị, có giống (hoặc giống hệt) với việc đặt tên mô tả tập tin không?
Xen2050

@ Xen2050 Thành thật mà nói tôi không biết. Kinh nghiệm rõ ràng của tôi với mô tả tập tin (trong bashhoặc ở nơi khác) là rất hạn chế. Tất nhiên tôi sử dụng chúng tất cả các thời gian. :) Các ống không tên ( |) là các bộ xếp hình phù du; ống được đặt tên là các bộ xếp hàng dai dẳng hơn với tên (đường dẫn). Cho đến bây giờ dường như có thể có một sự tương đồng, không phải là một danh tính.
Kamil Maciorowski

Cảm ơn bạn đã trả lời vấn đề của tôi. Tôi hiểu cách tiếp cận của bạn; Bạn có thấy bất kỳ cơ hội để thực hiện một giải pháp mà không sử dụng các ống có tên riêng biệt không? Lý tưởng nhất là sẽ chỉ có một dòng lệnh làm việc với các ống không tên, vì công việc nên được bắt đầu bằng một "nỗ lực kinh tế" từ dấu nhắc lệnh.
dùng415275

@ user415275 Tôi đã mở rộng câu trả lời của mình.
Kamil Maciorowski

Cảm ơn bạn rất nhiều vì đã trả lời. Dù sao, "một lớp lót" lớn của bạn vẫn sử dụng fifos / ống có tên - dù sao cũng có cơ hội đạt được những điều sau: - chỉ đọc ngày đầu vào một lần - từ đây, xử lý tất cả dữ liệu - và: tham gia dữ liệu kết quả sau đó một lần nữa, không có tên ống? Tôi hoàn toàn đánh giá cao công việc của bạn và sự cống hiến của bạn, và tất nhiên nó hoạt động, tuy nhiên, đó không phải là cách thực dụng mà tôi muốn chọn, miễn là có thể làm như vậy.
user415275
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.