Skip to content

Commit

Permalink
Merge pull request #102 from BrenekH/develop
Browse files Browse the repository at this point in the history
Add encoding device (#101)
  • Loading branch information
BrenekH authored Jul 29, 2021
2 parents eeb5b1b + 3c807da commit 1335f4e
Show file tree
Hide file tree
Showing 16 changed files with 137 additions and 26 deletions.
12 changes: 7 additions & 5 deletions controller/controller/libraries.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,10 @@ func updateLibraryQueue(l libraries.Library, wg *sync.WaitGroup, completeMap *ma
continue
}

var ffmpegCodec string
var ffmpegCodec, hwDevice string
if l.Pipeline.UseHardware {
ffmpegCodec = l.Pipeline.HardwareCodec
hwDevice = l.Pipeline.HWDevice
} else {
ffmpegCodec = mapTargetCodecToFFmpegParameter(l.Pipeline.TargetVideoCodec)
}
Expand All @@ -148,14 +149,15 @@ func updateLibraryQueue(l libraries.Library, wg *sync.WaitGroup, completeMap *ma
UUID: u.String(),
Path: videoFilepath,
Parameters: dispatched.JobParameters{
Encode: !encodeVideo,
Stereo: !stereoAudioTrackExists,
Codec: ffmpegCodec,
Encode: !encodeVideo,
Stereo: !stereoAudioTrackExists,
Codec: ffmpegCodec,
HWDevice: hwDevice,
},
RawMediaInfo: mediaInfo,
}

logger.Trace(fmt.Sprintf("%v Encode=%v Stereo=%v Codec=%v", videoFilepath, !encodeVideo, !stereoAudioTrackExists, ffmpegCodec))
logger.Trace(fmt.Sprintf("%v Encode=%v Stereo=%v Codec=%v HWDevice=%v", videoFilepath, !encodeVideo, !stereoAudioTrackExists, ffmpegCodec, hwDevice))

l.Queue.Push(job)
logger.Info(fmt.Sprintf("Added %v to the queue", job.Path))
Expand Down
7 changes: 4 additions & 3 deletions controller/db/dispatched/dispatched.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,10 @@ type Job struct {

// JobParameters represents the actions that need to be taken against a job.
type JobParameters struct {
Encode bool `json:"encode"` // true when the file's video stream needs to be encoded
Stereo bool `json:"stereo"` // true when the file is missing a stereo audio track
Codec string `json:"codec"` // the ffmpeg compatible video codec
Encode bool `json:"encode"` // true when the file's video stream needs to be encoded
Stereo bool `json:"stereo"` // true when the file is missing a stereo audio track
Codec string `json:"codec"` // the ffmpeg compatible video codec
HWDevice string `json:"hw_device"` // The hardware device to use for encoding. If HWDevice is an empty string, a device should not be added to the FFmpeg command.
}

// Equal is a custom equality check for the Job type
Expand Down
1 change: 1 addition & 0 deletions controller/db/libraries/libraries.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type PluginPipeline struct { // TODO: Implement
SkipHDR bool `json:"skip_hdr"`
UseHardware bool `json:"use_hardware"`
HardwareCodec string `json:"hardware_codec"`
HWDevice string `json:"hw_device"`
}

type fileCache struct{} // TODO: Complete
Expand Down
2 changes: 1 addition & 1 deletion controller/db/libraries/libraries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestToDBLibrary(t *testing.T) {
PathMasks: []string{},
}, want: dBLibrary{
FsCheckInterval: "1h1m1s",
Pipeline: []byte("{\"target_video_codec\":\"\",\"create_stereo_audio\":false,\"skip_hdr\":false,\"use_hardware\":false,\"hardware_codec\":\"\"}"),
Pipeline: []byte("{\"target_video_codec\":\"\",\"create_stereo_audio\":false,\"skip_hdr\":false,\"use_hardware\":false,\"hardware_codec\":\"\",\"hw_device\":\"\"}"),
Queue: []byte("{\"Items\":null}"),
FileCache: []byte("{}"),
PathMasks: []byte("[]"),
Expand Down
14 changes: 7 additions & 7 deletions controller/server/webfiles/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"files": {
"main.css": "/static/css/main.78f2d9f1.chunk.css",
"main.js": "/static/js/main.d61fc18f.chunk.js",
"main.js.map": "/static/js/main.d61fc18f.chunk.js.map",
"main.js": "/static/js/main.bc4fd1fa.chunk.js",
"main.js.map": "/static/js/main.bc4fd1fa.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.055bee68.js",
"runtime-main.js.map": "/static/js/runtime-main.055bee68.js.map",
"static/css/2.a49f93ba.chunk.css": "/static/css/2.a49f93ba.chunk.css",
"static/js/2.c2b3c604.chunk.js": "/static/js/2.c2b3c604.chunk.js",
"static/js/2.c2b3c604.chunk.js.map": "/static/js/2.c2b3c604.chunk.js.map",
"static/js/2.ed771b57.chunk.js": "/static/js/2.ed771b57.chunk.js",
"static/js/2.ed771b57.chunk.js.map": "/static/js/2.ed771b57.chunk.js.map",
"static/js/3.a09c83ab.chunk.js": "/static/js/3.a09c83ab.chunk.js",
"static/js/3.a09c83ab.chunk.js.map": "/static/js/3.a09c83ab.chunk.js.map",
"index.html": "/index.html",
"static/css/2.a49f93ba.chunk.css.map": "/static/css/2.a49f93ba.chunk.css.map",
"static/css/main.78f2d9f1.chunk.css.map": "/static/css/main.78f2d9f1.chunk.css.map",
"static/js/2.c2b3c604.chunk.js.LICENSE.txt": "/static/js/2.c2b3c604.chunk.js.LICENSE.txt",
"static/js/2.ed771b57.chunk.js.LICENSE.txt": "/static/js/2.ed771b57.chunk.js.LICENSE.txt",
"static/media/Encodarr-Logo.4b0cc1bf.svg": "/static/media/Encodarr-Logo.4b0cc1bf.svg",
"static/media/Info-I.ffc9d3a2.svg": "/static/media/Info-I.ffc9d3a2.svg",
"static/media/addLibraryIcon.dd5f1d29.svg": "/static/media/addLibraryIcon.dd5f1d29.svg",
Expand All @@ -23,8 +23,8 @@
"entrypoints": [
"static/js/runtime-main.055bee68.js",
"static/css/2.a49f93ba.chunk.css",
"static/js/2.c2b3c604.chunk.js",
"static/js/2.ed771b57.chunk.js",
"static/css/main.78f2d9f1.chunk.css",
"static/js/main.d61fc18f.chunk.js"
"static/js/main.bc4fd1fa.chunk.js"
]
}
2 changes: 1 addition & 1 deletion controller/server/webfiles/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000e30"/><meta name="description" content="Encode media libraries"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"/><meta name="msapplication-TileColor" content="#2b5797"/><title>Encodarr</title><link href="/static/css/2.a49f93ba.chunk.css" rel="stylesheet"><link href="/static/css/main.78f2d9f1.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],s=0,p=[];s<i.length;s++)a=i[s],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&p.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);p.length;)p.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+"static/js/"+({}[e]||e)+"."+{3:"a09c83ab"}[e]+".chunk.js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/",a.oe=function(e){throw console.error(e),e};var i=this["webpackJsonpencodarr-react-frontend"]=this["webpackJsonpencodarr-react-frontend"]||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([])</script><script src="/static/js/2.c2b3c604.chunk.js"></script><script src="/static/js/main.d61fc18f.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000e30"/><meta name="description" content="Encode media libraries"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"/><meta name="msapplication-TileColor" content="#2b5797"/><title>Encodarr</title><link href="/static/css/2.a49f93ba.chunk.css" rel="stylesheet"><link href="/static/css/main.78f2d9f1.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],s=0,p=[];s<i.length;s++)a=i[s],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&p.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);p.length;)p.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+"static/js/"+({}[e]||e)+"."+{3:"a09c83ab"}[e]+".chunk.js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/",a.oe=function(e){throw console.error(e),e};var i=this["webpackJsonpencodarr-react-frontend"]=this["webpackJsonpencodarr-react-frontend"]||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([])</script><script src="/static/js/2.ed771b57.chunk.js"></script><script src="/static/js/main.bc4fd1fa.chunk.js"></script></body></html>
3 changes: 3 additions & 0 deletions controller/server/webfiles/static/js/2.ed771b57.chunk.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/

/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions controller/server/webfiles/static/js/main.bc4fd1fa.chunk.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

41 changes: 40 additions & 1 deletion frontend/src/tabs/LibrariesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ interface ILibraryCardState {
skip_hdr: boolean,
use_hardware: boolean,
hardware_codec: string,
hw_device: string,

showEditModal: boolean,
showQueueModal: boolean,
Expand All @@ -110,6 +111,7 @@ class LibraryCard extends React.Component<ILibraryCardProps, ILibraryCardState>
skip_hdr: true,
use_hardware: false,
hardware_codec: "",
hw_device: "",

showEditModal: false,
showQueueModal: false,
Expand All @@ -133,6 +135,7 @@ class LibraryCard extends React.Component<ILibraryCardProps, ILibraryCardState>
skip_hdr: response.data.pipeline.skip_hdr,
use_hardware: response.data.pipeline.use_hardware,
hardware_codec: response.data.pipeline.hardware_codec,
hw_device: response.data.pipeline.hw_device,
});
}).catch((error) => {
console.error(`Request to /api/web/v1/library/${this.props.id} failed with error: ${error}`)
Expand All @@ -149,8 +152,8 @@ class LibraryCard extends React.Component<ILibraryCardProps, ILibraryCardState>
<p className="text-center">Target Video Codec: {this.state.target_video_codec}</p>
<p className="text-center">Create Stereo Audio Track: {(this.state.create_stereo_audio) ? "True" : "False"}</p>
<p className="text-center">Skip HDR Files: {(this.state.skip_hdr) ? "True" : "False"}</p>
<p className="text-center">Use Hardware: {(this.state.use_hardware) ? "True" : "False"}</p>
{(this.state.use_hardware) ? <p className="text-center">Hardware Codec: {this.state.hardware_codec}</p> : null }
{(this.state.use_hardware) ? <p className="text-center">Hardware Device: {this.state.hw_device}</p> : null }
{(this.state.path_masks.length !== 0) ? <p className="text-center">Path Masks: {this.state.path_masks}</p> : null }
<Button variant="secondary" onClick={() => {this.setState({showQueueModal: true})}}>Queue</Button>
<Button variant="primary" onClick={() => {this.setState({showEditModal: true})}}>Edit</Button>
Expand All @@ -168,6 +171,7 @@ class LibraryCard extends React.Component<ILibraryCardProps, ILibraryCardState>
skip_hdr={this.state.skip_hdr}
use_hardware={this.state.use_hardware}
hardware_codec={this.state.hardware_codec}
hw_device={this.state.hw_device}
/>) : null}

{(this.state.showQueueModal) ? (<QueueModal
Expand All @@ -194,6 +198,7 @@ interface ICreateLibraryModalState {
skip_hdr: boolean,
use_hardware: boolean,
hardware_codec: string,
hw_device: string,
}

class CreateLibraryModal extends React.Component<ICreateLibraryModalProps, ICreateLibraryModalState> {
Expand All @@ -210,6 +215,7 @@ class CreateLibraryModal extends React.Component<ICreateLibraryModalProps, ICrea
skip_hdr: true,
use_hardware: false,
hardware_codec: "",
hw_device: "",
}

this.submitLib = this.submitLib.bind(this);
Expand All @@ -227,6 +233,7 @@ class CreateLibraryModal extends React.Component<ICreateLibraryModalProps, ICrea
skip_hdr: this.state.skip_hdr,
use_hardware: this.state.use_hardware,
hardware_codec: this.state.hardware_codec,
hw_device: this.state.hw_device,
},
};
axios.post("/api/web/v1/library/new", data).then(() => {
Expand Down Expand Up @@ -303,6 +310,8 @@ class CreateLibraryModal extends React.Component<ICreateLibraryModalProps, ICrea
/>
</InputGroup>

{(this.state.use_hardware) ? <h6>WARNING: Hardware encoding is untested and highly experimental. Use at your own risk. <a href="https://github.com/BrenekH/encodarr/wiki/Hardware-Encoding" target="_blank" rel="noreferrer">More info.</a></h6> : null}

{(this.state.use_hardware) ? <InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Hardware Codec</InputGroup.Text></InputGroup.Prepend>
<FormControl
Expand All @@ -315,6 +324,18 @@ class CreateLibraryModal extends React.Component<ICreateLibraryModalProps, ICrea
/>
</InputGroup> : null}

{(this.state.use_hardware) ? <InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Hardware Device</InputGroup.Text></InputGroup.Prepend>
<FormControl
className="dark-text-input"
placeholder="/dev/dri/renderD128"
aria-label="Hardware Device"
aria-describedby="basic-addon1"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { this.setState({ hw_device: event.target.value }); }}
value={this.state.hw_device}
/>
</InputGroup> : null}

<InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Create Stereo Audio Track</InputGroup.Text></InputGroup.Prepend>
<InputGroup.Checkbox
Expand Down Expand Up @@ -367,6 +388,7 @@ interface IEditLibraryModalProps {
skip_hdr: boolean,
use_hardware: boolean,
hardware_codec: string,
hw_device: string,
}

interface IEditLibraryModalState {
Expand All @@ -379,6 +401,7 @@ interface IEditLibraryModalState {
skip_hdr: boolean,
use_hardware: boolean,
hardware_codec: string,
hw_device: string,
}

class EditLibraryModal extends React.Component<IEditLibraryModalProps, IEditLibraryModalState> {
Expand All @@ -395,6 +418,7 @@ class EditLibraryModal extends React.Component<IEditLibraryModalProps, IEditLibr
skip_hdr: props.skip_hdr,
use_hardware: props.use_hardware,
hardware_codec: props.hardware_codec,
hw_device: props.hw_device,
}

this.putChanges = this.putChanges.bind(this);
Expand All @@ -413,6 +437,7 @@ class EditLibraryModal extends React.Component<IEditLibraryModalProps, IEditLibr
skip_hdr: this.state.skip_hdr,
use_hardware: this.state.use_hardware,
hardware_codec: this.state.hardware_codec,
hw_device: this.state.hw_device,
},
};
axios.put(`/api/web/v1/library/${this.props.id}`, data).then(() => {
Expand Down Expand Up @@ -496,6 +521,8 @@ class EditLibraryModal extends React.Component<IEditLibraryModalProps, IEditLibr
/>
</InputGroup>

{(this.state.use_hardware) ? <h6>WARNING: Hardware encoding is untested and highly experimental. Use at your own risk. <a href="https://github.com/BrenekH/encodarr/wiki/Hardware-Encoding" target="_blank" rel="noreferrer">More info.</a></h6> : null}

{(this.state.use_hardware) ? <InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Hardware Codec</InputGroup.Text></InputGroup.Prepend>
<FormControl
Expand All @@ -508,6 +535,18 @@ class EditLibraryModal extends React.Component<IEditLibraryModalProps, IEditLibr
/>
</InputGroup> : null}

{(this.state.use_hardware) ? <InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Hardware Device</InputGroup.Text></InputGroup.Prepend>
<FormControl
className="dark-text-input"
placeholder="/dev/dri/renderD128"
aria-label="Hardware Device"
aria-describedby="basic-addon1"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { this.setState({ hw_device: event.target.value }); }}
value={this.state.hw_device}
/>
</InputGroup> : null}

<InputGroup className="mb-3">
<InputGroup.Prepend><InputGroup.Text>Create Stereo Audio Track</InputGroup.Text></InputGroup.Prepend>
<InputGroup.Checkbox
Expand Down
Loading

0 comments on commit 1335f4e

Please sign in to comment.